spring-projects/spring-security · error · IllegalArgumentException

Invalid len

Error message

Invalid len

What it means

BCrypt.encode_base64() encodes len bytes of d into bcrypt's custom base64 alphabet. It throws this IllegalArgumentException when len is <= 0 or exceeds d.length, i.e. when asked to encode zero bytes or more bytes than the array holds. This is an internal-argument sanity check protecting against buffer overreads.

Source

Thrown at crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java:231

	private int P[] = new int[0];

	private int S[] = new int[0];

	/**
	 * Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note
	 * that this is <strong>not</strong> compatible with the standard MIME-base64
	 * encoding.
	 * @param d the byte array to encode
	 * @param len the number of bytes to encode
	 * @param rs the destination buffer for the base64-encoded string
	 * @exception IllegalArgumentException if the length is invalid
	 */
	static void encode_base64(byte d[], int len, StringBuilder rs) throws IllegalArgumentException {
		int off = 0;
		int c1, c2;

		if (len <= 0 || len > d.length) {
			throw new IllegalArgumentException("Invalid len");
		}

		while (off < len) {
			c1 = d[off++] & 0xff;
			rs.append(base64_code[(c1 >> 2) & 0x3f]);
			c1 = (c1 & 0x03) << 4;
			if (off >= len) {
				rs.append(base64_code[c1 & 0x3f]);
				break;
			}
			c2 = d[off++] & 0xff;
			c1 |= (c2 >> 4) & 0x0f;
			rs.append(base64_code[c1 & 0x3f]);
			c1 = (c2 & 0x0f) << 2;
			if (off >= len) {
				rs.append(base64_code[c1 & 0x3f]);
				break;
			}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Check that the byte array passed to hashpw/gensalt is non-empty and correctly sized (salt: 16 raw bytes)
  2. Do not call encode_base64 directly; use the public hashpw(String, String) API
  3. If you forked BCrypt.java, audit the len/offset arithmetic at the call site

Example fix

// before
BCrypt.encode_base64(new byte[0], 8, sb); // len > d.length
// after
byte[] data = Arrays.copyOf(saltBytes, 16); // ensure capacity >= len
BCrypt.encode_base64(data, 16, sb);
Defensive patterns

Strategy: try-catch

Validate before calling

static boolean canEncode(byte[] d, int len) {
    return len > 0 && len <= d.length;
}

Type guard

if (data == null || data.length == 0) throw new IllegalArgumentException("data must be non-empty");

Try / catch

try {
    BCrypt.encode_base64(data, len, sb);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("encode_base64 length invariant violated: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling encode_base64 with len <= 0 or len > d.length — typically via hashpw or gensalt with corrupted internal state, or direct calls with a wrong length argument.

Common situations: Direct use of BCrypt internals (package-private/static misuse); modified forks of BCrypt.java passing wrong offsets; empty input byte arrays reaching hashing internals.

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 spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/1a6b382bfbd3d7d8. Report an issue: GitHub.