Quarkus 使用哪个版本的 bcrypt 以及如何生成有效的哈希值?

Which version of bcrypt is used in Quarkus and how to generate valid hashes?

我们目前正在将我们的应用程序从 payara 迁移到 Quarkus 并且遇到了 bCrypt 映射器的问题。
我们无法正确生成正确的哈希值,因为我们不知道使用的是哪个版本的 bCrypt。我们尝试使用您的 github 中的示例哈希,效果很好,但是当我们尝试使用我们自己生成的哈希时,它没有。
我们尝试使用多个在线生成器,但我们无法找出 Quarkus 中使用的是哪个版本。然后我们尝试使用 wildfly 生成器代码片段(见下文),因为我们认为它会使用与 quarkus 相同的算法,但这也没有用。

static final Provider ELYTRON_PROVIDER = new WildFlyElytronProvider();

    static final String TEST_PASSWORD = "test";

    public static void main(String[] args) {

        PasswordFactory passwordFactory = null;
        try {
            passwordFactory = PasswordFactory.getInstance(BCryptPassword.ALGORITHM_BCRYPT, ELYTRON_PROVIDER);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        int iterationCount = 10;

        byte[] salt = new byte[BCryptPassword.BCRYPT_SALT_SIZE];
        SecureRandom random = new SecureRandom();
        random.nextBytes(salt);

        IteratedSaltedPasswordAlgorithmSpec iteratedAlgorithmSpec = new IteratedSaltedPasswordAlgorithmSpec(iterationCount, salt);
        EncryptablePasswordSpec encryptableSpec = new EncryptablePasswordSpec(TEST_PASSWORD.toCharArray(), iteratedAlgorithmSpec);

        BCryptPassword original = null;
        try {
            original = (BCryptPassword) passwordFactory.generatePassword(encryptableSpec);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        byte[] hash = original.getHash();

        Base64.Encoder encoder = Base64.getEncoder();
        System.out.println("Encoded Salt = " + encoder.encodeToString(salt));
        System.out.println("Encoded Hash = " + encoder.encodeToString(hash));
    }

当我们从 bCrypt 切换到 clear 时,它也工作正常,这意味着数据库工作正常。 由于示例哈希工作正常,我们认为配置没有错误,但这里是我们的配置以防万一:

# h2 datasource
#quarkus.datasource.url = jdbc:h2:mem:test
#quarkus.datasource.driver = org.h2.Driver
#quarkus.datasource.username = sa
#quarkus.datasource.password =

# postgres configuration
quarkus.datasource.url = jdbc:postgresql://localhost:5432/postgres
quarkus.datasource.driver = org.postgresql.Driver
quarkus.datasource.username = postgres
quarkus.datasource.password = postgres

#Authorisierung
quarkus.http.auth.basic=true
quarkus.security.jdbc.realm-name=quarkus
quarkus.security.jdbc.enabled=true
quarkus.security.jdbc.principal-query.sql=SELECT n.hash, n.salt, n.iterations FROM nutzer n WHERE n.nutzername=?
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.enabled=true
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.password-index=1
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.salt-index=2
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.iteration-count-index=3
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.hash-encoding=BASE64

quarkus.security.jdbc.principal-query.roles.sql=SELECT nb.berechtigungen_name FROM nutzer n JOIN nutzer_berechtigung nb ON nb.nutzers_nutzername = n.nutzername WHERE n.nutzername=?
quarkus.security.jdbc.principal-query.roles.datasource=permissions
quarkus.security.jdbc.principal-query.roles.attribute-mappings.0.index=1
quarkus.security.jdbc.principal-query.roles.attribute-mappings.0.to=groups

# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.database.generation=drop-and-create

#Always include swagger-ui
quarkus.swagger-ui.always-include=true

我们没有收到错误消息,只是无法验证用户。

是我们的配置有误,还是我们使用了错误的算法或 bCrypt 版本?

您可以使用 wildfly github 中的示例生成有效的散列和盐:

static final Provider ELYTRON_PROVIDER = new WildFlyElytronPasswordProvider();
static final String TEST_PASSWORD = "myPassword";

public static void main(String[] args) throws Exception {
    PasswordFactory passwordFactory = PasswordFactory.getInstance(BCryptPassword.ALGORITHM_BCRYPT, ELYTRON_PROVIDER);

    int iterationCount = 10;

    byte[] salt = new byte[BCryptPassword.BCRYPT_SALT_SIZE];
    SecureRandom random = new SecureRandom();
    random.nextBytes(salt);

    IteratedSaltedPasswordAlgorithmSpec iteratedAlgorithmSpec = new IteratedSaltedPasswordAlgorithmSpec(iterationCount, salt);
    EncryptablePasswordSpec encryptableSpec = new EncryptablePasswordSpec(TEST_PASSWORD.toCharArray(), iteratedAlgorithmSpec);

    BCryptPassword original = (BCryptPassword) passwordFactory.generatePassword(encryptableSpec);

    byte[] hash = original.getHash();

    Encoder encoder = Base64.getEncoder();
    System.out.println("Encoded Salt = " + encoder.encodeToString(salt));
    System.out.println("Encoded Hash = " + encoder.encodeToString(hash));
}

请注意,WildFlyElytronProvider() 目前已被弃用,因此您必须改用 WildFlyElytronPasswordProvider()。