spring-projects/spring-security · error · IllegalArgumentException

Invalid RSA Private Key ASN1 sequence.

Error message

Invalid RSA Private Key ASN1 sequence.

What it means

After base64-decoding PEM content, parseKeyPair() parses the DER bytes as an ASN1Sequence and requires exactly 9 elements for a PKCS#1 RSAPrivateKey structure. This error means the decoded ASN.1 sequence has the wrong number of fields, so the data is not a valid RSA PRIVATE KEY (PKCS#1) structure.

Source

Thrown at crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaKeyHelper.java:98

			catch (Exception ex) {
				// Ignore
			}
			throw new IllegalArgumentException("String is not PEM encoded data, nor a public key encoded for ssh");
		}

		String type = m.group(1);
		final byte[] content = base64Decode(m.group(2));

		PublicKey publicKey;
		PrivateKey privateKey = null;

		try {
			KeyFactory fact = KeyFactory.getInstance("RSA");
			switch (type) {
				case "RSA PRIVATE KEY" -> {
					ASN1Sequence seq = ASN1Sequence.getInstance(content);
					if (seq.size() != 9) {
						throw new IllegalArgumentException("Invalid RSA Private Key ASN1 sequence.");
					}
					org.bouncycastle.asn1.pkcs.RSAPrivateKey key = org.bouncycastle.asn1.pkcs.RSAPrivateKey
						.getInstance(seq);
					RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent());
					RSAPrivateCrtKeySpec privSpec = new RSAPrivateCrtKeySpec(key.getModulus(), key.getPublicExponent(),
							key.getPrivateExponent(), key.getPrime1(), key.getPrime2(), key.getExponent1(),
							key.getExponent2(), key.getCoefficient());
					publicKey = fact.generatePublic(pubSpec);
					privateKey = fact.generatePrivate(privSpec);
				}
				case "PUBLIC KEY" -> {
					KeySpec keySpec = new X509EncodedKeySpec(content);
					publicKey = fact.generatePublic(keySpec);
				}
				case "RSA PUBLIC KEY" -> {
					ASN1Sequence seq = ASN1Sequence.getInstance(content);
					org.bouncycastle.asn1.pkcs.RSAPublicKey key = org.bouncycastle.asn1.pkcs.RSAPublicKey
						.getInstance(seq);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Convert the key to PKCS#1: openssl rsa -in key.pem -traditional -out rsakey.pem
  2. Verify the base64 body is complete and unmodified between BEGIN/END lines
  3. Match the PEM header to the actual format (BEGIN PRIVATE KEY = PKCS#8, BEGIN RSA PRIVATE KEY = PKCS#1)
  4. Re-extract the key: openssl rsa -in bad.pem -check

Example fix

// before
openssl pkcs8 -topk8 -in rsa.pem   // produces PKCS#8, seq size != 9
// after
openssl rsa -in key.pem -traditional -out rsa_pkcs1.pem
Defensive patterns

Strategy: validation

Validate before calling

// Confirm PKCS#1 format before parsing
String body = pem.replaceAll("-----(BEGIN|END) RSA PRIVATE KEY-----", "").replaceAll("\\s", "");
byte[] der = Base64.getMimeDecoder().decode(body);
if (der[4] != 0x30) throw new IllegalArgumentException("Not DER sequence");

Try / catch

try { return RsaKeyHelper.parseKeyPair(pem); } catch (IllegalArgumentException ex) { if (ex.getMessage().contains("ASN1")) { /* convert key with openssl and retry once */ } throw ex; }

Prevention

When it happens

Trigger: Passing a 'PRIVATE KEY' (PKCS#8) PEM but labeled or routed into the 'RSA PRIVATE KEY' branch; truncated or corrupted base64 body; passing a public key or certificate body under an RSA PRIVATE KEY header.

Common situations: Key generated by OpenSSL in PKCS#8 format (openssl genpkey) instead of traditional PKCS#1 (openssl genrsa); manual header edits; copy-paste truncation of the long base64 block.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/f6ebafc5f19081cb. Report an issue: GitHub.