spring-projects/spring-security · error · IOException
Expected
Error message
Expected
What it means
After reading the 4-byte length header, readBigInteger reads exactly l key bytes; if the stream has fewer bytes than the declared length, the blob is malformed and this IOException ('Expected <l> key bytes') is thrown.
Source
Thrown at crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaKeyHelper.java:279
data[2] = (byte) ((length >> 8) & 0xFF);
data[3] = (byte) (length & 0xFF);
stream.write(data);
stream.write(num.toByteArray());
}
private static byte[] readBigInteger(ByteArrayInputStream in) throws IOException {
byte[] b = new byte[4];
if (in.read(b) != 4) {
throw new IOException("Expected length data as 4 bytes");
}
int l = ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16) | ((b[2] & 0xFF) << 8) | (b[3] & 0xFF);
b = new byte[l];
if (in.read(b) != l) {
throw new IOException("Expected " + l + " key bytes");
}
return b;
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Restore the full key from its source (regenerate with ssh-keygen if lost).
- Strip all whitespace/newlines from the base64 body before parsing.
- Confirm the key's integrity with ssh-keygen -l -f keyfile.
- Catch the RuntimeException and inspect getCause() to surface this message to the user.
Example fix
// before
String key = pastedKey.replaceAll("\\s", "").substring(0, 300); // truncated
helper.extractPublicKey(key);
// after
String key = pastedKey.trim();
if (key.split("\\s+")[1].length() >= 372) { // typical 2048-bit ssh-rsa body
helper.extractPublicKey(key);
} Defensive patterns
Strategy: validation
Validate before calling
boolean lengthsConsistent(byte[] blob) {
int off = 11;
while (off + 4 <= blob.length) {
int l = ((blob[off] & 0xFF) << 24) | ((blob[off+1] & 0xFF) << 16) | ((blob[off+2] & 0xFF) << 8) | (blob[off+3] & 0xFF);
if (l < 0 || off + 4 + l > blob.length) return false;
off += 4 + l;
if (off == blob.length) return true;
}
return false;
} Try / catch
try {
RSAPublicKey pk = helper.extractPublicKey(key);
} catch (RuntimeException e) {
if (e.getCause() != null && e.getCause().getMessage().contains("key bytes")) {
throw new ConfigException("Declared key length exceeds available bytes — key is truncated or corrupted");
}
throw e;
} Prevention
- Verify the full key with 'ssh-keygen -l -f' before storing it in config.
- Avoid pasting keys through channels that trim long lines (chat, tickets).
- Store keys verbatim in files and read them programmatically.
- Validate base64 decodes to a structurally consistent blob pre-parse.
When it happens
Trigger: The SSH blob declares a field length (e.g. exponent or modulus size) larger than the remaining bytes — truncated base64 or a corrupted/edited key body.
Common situations: Copy/paste truncation of long RSA keys, line-wrapping tools inserting whitespace that broke base64 decoding assumptions, or corrupted uploads of authorized_keys content.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Expected length data as 4 bytes
- Only RSA is currently supported, but algorithm was
- SSH key prefix not found
- Cannot load keys from store:
- String is not PEM encoded data, nor a public key encoded for
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/2df643d8da46fd18.
Report an issue: GitHub.