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
- Generate the salt as exactly 16 random bytes: new SecureRandom().generateSeed(16) or a 16-byte array.
- If deriving the salt from a string, decode to exactly 16 bytes or pad/trim deterministically before calling.
- 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
- Prefer BcryptUtil.bcryptHash(password) which generates its own salt.
- Always allocate salt arrays of exactly BCryptPassword.BCRYPT_SALT_SIZE (16).
- Don't reuse digests (SHA-256 output is 32 bytes) as bcrypt salts.
- Document the 16-byte requirement wherever salt generation happens.
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
- Iteration count must be greater than zero
- No producers for required item %s, step builder used: %s
- cycle detection failure report (dynamic CycleBuildException
- Build step '%s' does not produce any build item and thus wil
- Cannot consume/produce interface or abstract class build ite
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/cbc48ee8bb055ebd.
Report an issue: GitHub.