spring-projects/spring-security · error · IOException
Expected length data as 4 bytes
Error message
Expected length data as 4 bytes
What it means
readBigInteger reads a 4-byte big-endian length header from the SSH key blob stream. If fewer than 4 bytes remain, the blob is truncated/malformed and this IOException is thrown (often surfacing as the message-less RuntimeException at line 243).
Source
Thrown at crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaKeyHelper.java:271
}
}
private static void writeBigInteger(ByteArrayOutputStream stream, BigInteger num) throws IOException {
int length = num.toByteArray().length;
byte[] data = new byte[4];
data[0] = (byte) ((length >> 24) & 0xFF);
data[1] = (byte) ((length >> 16) & 0xFF);
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
- Supply the complete, unmodified key string including the full base64 body.
- Verify the key with ssh-keygen before use.
- Ensure the algorithm token is 'ssh-rsa' so blob layout expectations match.
- Handle the wrapped IOException via getCause() to give users a meaningful message.
Example fix
// before
String body = "AAAAB"; // truncated base64
helper.extractPublicKey("ssh-rsa " + body);
// after
String body = Files.readString(Path.of("id_rsa.pub")).split(" ")[1]; // complete base64
helper.extractPublicKey("ssh-rsa " + body); Defensive patterns
Strategy: validation
Validate before calling
boolean hasFullBlob(String base64Body) {
try {
byte[] b = Base64.getDecoder().decode(base64Body);
if (b.length < 15) return false;
int l = ((b[11] & 0xFF) << 24) | ((b[12] & 0xFF) << 16) | ((b[13] & 0xFF) << 8) | (b[14] & 0xFF);
return 11 + 4 + l <= b.length;
} catch (IllegalArgumentException ex) { return false; }
} Try / catch
try {
RSAPublicKey pk = helper.extractPublicKey(key);
} catch (RuntimeException e) {
if (e.getCause() instanceof IOException) {
throw new ConfigException("SSH key blob truncated: " + e.getCause().getMessage());
}
throw e;
} Prevention
- Never truncate base64 bodies when copying keys.
- Strip whitespace consistently before decoding.
- Use file-based key loading to avoid manual edits.
- Fail fast with getCause() details.
When it happens
Trigger: Parsing an SSH-RSA blob that ends right after the prefix or between fields — i.e. the decoded base64 payload is shorter than the SSH wire structure requires.
Common situations: Partially copied .pub key content, keys that were base64-decoded twice or incorrectly, or non-RSA blob formats (e.g. ed25519 bodies) whose layout misaligns parsing.
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
- Only RSA is currently supported, but algorithm was
- Cannot encode key
- SSH key prefix not found
- Cannot load keys from store:
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/97500f15b556eb18.
Report an issue: GitHub.