quarkusio/quarkus · error · IllegalArgumentException

Salt length must be exactly 16 bytes

Error message

Salt length must be exactly 16 bytes

What it means

BcryptUtil.bcryptHash(password, iterationCount, salt) requires the salt byte array to be exactly BCryptPassword.BCRYPT_SALT_SIZE (16) bytes, matching Elytron's BCrypt specification. Any other length throws IllegalArgumentException, because BCrypt's algorithm fixes the salt size.

Source

Thrown at extensions/elytron-security-common/runtime/src/main/java/io/quarkus/elytron/security/common/BcryptUtil.java:71

     * Produces a Modular Crypt Format bcrypt hash of the given password, using the specified salt and the specified iteration
     * count.
     *
     * @param password the password to hash
     * @param iterationCount the number of iterations to use while hashing
     * @param salt the salt to use while hashing
     * @return the Modular Crypt Format bcrypt hash of the given password
     * @throws NullPointerException if the password or salt are null
     * @throws IllegalArgumentException if the iterationCount parameter is negative or zero, or if the salt length is not equal
     *         to 16
     */
    public static String bcryptHash(String password, int iterationCount, byte[] salt) {
        if (iterationCount <= 0) {
            throw new IllegalArgumentException("Iteration count must be greater than zero");
        }
        Objects.requireNonNull(password, "password is required");
        Objects.requireNonNull(salt, "salt is required");
        if (salt.length != BCryptPassword.BCRYPT_SALT_SIZE) {
            throw new IllegalArgumentException("Salt length must be exactly " + BCryptPassword.BCRYPT_SALT_SIZE + " bytes");
        }

        PasswordFactory passwordFactory;
        try {
            passwordFactory = PasswordFactory.getInstance(BCryptPassword.ALGORITHM_BCRYPT, provider);
        } catch (NoSuchAlgorithmException e) {
            // can't really happen
            throw new RuntimeException(e);
        }

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

        try {
            BCryptPassword original = (BCryptPassword) passwordFactory.generatePassword(encryptableSpec);
            return ModularCrypt.encodeAsString(original);
        } catch (InvalidKeySpecException e) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Generate the salt as exactly 16 random bytes: new SecureRandom().generateSeed(16) or a 16-byte array.
  2. If deriving the salt from a string, decode to exactly 16 bytes or pad/trim deterministically before calling.
  3. Prefer the 1-arg BcryptUtil.bcryptHash(password), which generates a compliant salt internally.

Example fix

// before
byte[] salt = new SecureRandom().generateSeed(32);
String hash = BcryptUtil.bcryptHash(pwd, 10, salt);
// after
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
String hash = BcryptUtil.bcryptHash(pwd, 10, salt);
Defensive patterns

Strategy: validation

Validate before calling

// ensure a compliant 16-byte salt before hashing
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
if (salt.length != 16) throw new IllegalStateException();
String hash = BcryptUtil.bcryptHash(password, 10, salt);

Prevention

When it happens

Trigger: Passing a salt generated with a different length — e.g. Base64-decoded string of the wrong size, a 32-byte SHA-256 digest used as salt, or a salt taken from another algorithm's output.

Common situations: Generating the salt with new SecureRandom().generateSeed(24) or similar; reusing a salt string stored with encoding that changes its byte length; hard-coding a sample salt shorter than 16 bytes in tests.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/cbc48ee8bb055ebd. Report an issue: GitHub.