Error message
algid parse error, not a sequence
Also printed as
- java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
- java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: Unable to decode key
On JDK 8–11 the exception text itself reads "InvalidKeyException: IOException : algid parse error, not a sequence". Newer JDKs (checked on 21 and 25) say "Unable to decode key" and keep "algid parse error, not a sequence" in the `Caused by:` line of the stack trace.
Java (JDK) — KeyFactory.generatePrivate / generatePublic with PKCS8EncodedKeySpec or X509EncodedKeySpec
What it means
The bytes you wrapped in a `PKCS8EncodedKeySpec` or `X509EncodedKeySpec` do not start with the structure that spec promises: both formats begin with a SEQUENCE that holds an AlgorithmIdentifier ("algid"), and the JDK found something else there. The classic case is a PKCS#1 RSA key (`-----BEGIN RSA PRIVATE KEY-----`), whose first element is an INTEGER. The JDK reads only PKCS#8 for private keys and X.509 SubjectPublicKeyInfo for public keys.
Why it happens
A PKCS#1 key ("BEGIN RSA PRIVATE KEY")
commonOpenSSL 1.x `genrsa`, many hosting panels and older tooling write PKCS#1. Its DER is the RSAPrivateKey sequence without the algorithm identifier that PKCS#8 adds, so the JDK cannot find the algid.
Public and private specs swapped
commonA private key passed to `X509EncodedKeySpec`, or a public key to `PKCS8EncodedKeySpec`. The structures differ right after the outer SEQUENCE.
Not the DER bytes of the key
occasionalPEM text passed as bytes, base64 decoded twice, or a key from a keystore exported in another format. These usually fail with a different `Caused by` ("extra data at the end", "DerInputStream.getLength()"), but the algid message appears when the first bytes happen to parse.
A certificate instead of a key
occasional`-----BEGIN CERTIFICATE-----` contents are an X.509 certificate, not a SubjectPublicKeyInfo. Load it with `CertificateFactory` and call `getPublicKey()`.
How to fix it
- 1.
Convert the key to PKCS#8 / SPKI once
One OpenSSL command turns PKCS#1 keys into the formats the JDK reads natively.
bash # "-----BEGIN RSA PRIVATE KEY-----" (PKCS#1) -> "-----BEGIN PRIVATE KEY-----" (PKCS#8) openssl pkcs8 -topk8 -nocrypt -in rsa-pkcs1.pem -out private-pkcs8.pem # "-----BEGIN RSA PUBLIC KEY-----" -> "-----BEGIN PUBLIC KEY-----" (X.509 SubjectPublicKeyInfo) openssl rsa -RSAPublicKey_in -in rsa-public-pkcs1.pem -pubout -out public.pem - 2.
Strip the armour and check the label
Decode only the base64 body, and reject PEM labels the JDK cannot read with a clear message instead of a parse error.
java import java.nio.file.*; import java.security.*; import java.security.spec.*; import java.util.Base64; static PrivateKey loadPkcs8(Path path, String algorithm) throws Exception { String pem = Files.readString(path); if (!pem.contains("-----BEGIN PRIVATE KEY-----")) { throw new IllegalArgumentException("expected a PKCS#8 'BEGIN PRIVATE KEY' file"); } String body = pem.replaceAll("-----[A-Z ]+-----", "").replaceAll("\\s", ""); return KeyFactory.getInstance(algorithm).generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(body))); } static PublicKey loadSpki(Path path, String algorithm) throws Exception { String body = Files.readString(path).replaceAll("-----[A-Z ]+-----", "").replaceAll("\\s", ""); return KeyFactory.getInstance(algorithm).generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(body))); } - 3.
Or read every PEM flavour with Bouncy Castle
`PEMParser` understands PKCS#1, PKCS#8, SEC 1 and encrypted PEM, and `JcaPEMKeyConverter` turns the result into JCA keys.
java // With Bouncy Castle (bcpkix): reads PKCS#1, PKCS#8, SEC 1 and encrypted keys try (var parser = new org.bouncycastle.openssl.PEMParser(Files.newBufferedReader(path))) { Object object = parser.readObject(); var converter = new org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter(); PrivateKey key = object instanceof org.bouncycastle.openssl.PEMKeyPair pair ? converter.getKeyPair(pair).getPrivate() : converter.getPrivateKey((org.bouncycastle.asn1.pkcs.PrivateKeyInfo) object); }
Related errors
x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this ke…Go crypto/x509java.lang.IllegalArgumentException: Illegal base64 character 2dJava (JDK)System.Security.Cryptography.CryptographicException: ASN1 corrupted data..NET System.Security.CryptographyCould not deserialize key data. The data may be in an incorrect format, it may…Python cryptography