Mensaje de error
x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)
También se muestra como
- x509: failed to parse private key (use ParseECPrivateKey instead for this key format)
- x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)
- x509: failed to parse public key (use ParsePKCS1PublicKey instead for this key format)
La función entre paréntesis depende de lo que Go detecte: `ParsePKCS1PrivateKey`, `ParseECPrivateKey` o `ParsePKCS8PrivateKey`. El equivalente para claves públicas es «x509: failed to parse public key (use ParsePKCS1PublicKey instead for this key format)». Los bytes que no coinciden con ninguno de los formatos dan en cambio un `asn1: structure error`.
Go crypto/x509 — ParsePKCS8PrivateKey / ParsePKCS1PrivateKey / ParseECPrivateKey / ParsePKIXPublicKey
Qué significa
Le pasas al analizador de un contenedor de clave privada los bytes DER de otro, y Go reconoce de qué contenedor se trata en realidad. Hay tres codificaciones habituales: PKCS#8 (`-----BEGIN PRIVATE KEY-----`, cualquier algoritmo), PKCS#1 (`-----BEGIN RSA PRIVATE KEY-----`, solo RSA) y SEC 1 (`-----BEGIN EC PRIVATE KEY-----`, solo EC). La pista entre paréntesis indica la función que analizará tus bytes. La clave en sí está bien.
Por qué ocurre
Clave RSA en PKCS#1, el código espera PKCS#8
frecuente`openssl genrsa` (OpenSSL 1.x) y muchas herramientas antiguas escriben `RSA PRIVATE KEY`; el código escrito para la salida de `openssl genpkey` llama a `ParsePKCS8PrivateKey`. Con herramientas más recientes también ocurre al revés.
Clave EC en formato SEC 1
frecuente`openssl ecparam -genkey` escribe `EC PRIVATE KEY` (SEC 1, RFC 5915). Hay que pasarla a `ParseECPrivateKey` o convertirla a PKCS#8.
Clave pública RSA en PKCS#1 pasada a ParsePKIXPublicKey
ocasional`-----BEGIN RSA PUBLIC KEY-----` es la estructura PKCS#1 desnuda, sin el identificador de algoritmo que lleva `PUBLIC KEY` (SPKI).
Cómo solucionarlo
- 1.
Elegir el analizador según el tipo PEM
La etiqueta PEM te indica el contenedor. Decide según `block.Type` en lugar de dar por hecho un único formato.
go func parsePrivateKeyPEM(data []byte) (crypto.Signer, error) { block, _ := pem.Decode(data) if block == nil { return nil, errors.New("no PEM block found") } switch block.Type { case "PRIVATE KEY": // PKCS#8: RSA, ECDSA, Ed25519, X25519 key, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { return nil, err } signer, ok := key.(crypto.Signer) if !ok { return nil, fmt.Errorf("%T cannot sign", key) } return signer, nil case "RSA PRIVATE KEY": // PKCS#1 return x509.ParsePKCS1PrivateKey(block.Bytes) case "EC PRIVATE KEY": // SEC 1 return x509.ParseECPrivateKey(block.Bytes) default: return nil, fmt.Errorf("unsupported PEM type %q", block.Type) } } - 2.
Normalizar las claves a PKCS#8 y SPKI
PKCS#8 para las claves privadas y SPKI para las claves públicas funcionan con todos los algoritmos y todas las bibliotecas modernas. Convierte una sola vez, al aprovisionar las claves.
bash # Normalise any private key to PKCS#8 ("-----BEGIN PRIVATE KEY-----") openssl pkcs8 -topk8 -nocrypt -in legacy.pem -out key.pk8.pem # Public keys: PKCS#1 "RSA PUBLIC KEY" -> SPKI "PUBLIC KEY" openssl rsa -RSAPublicKey_in -in rsa-pub.pem -pubout -out spki.pem
Errores relacionados
asn1: structure error: tags don't matchGo encoding/asn1algid parse error, not a sequenceJava (JDK)System.Security.Cryptography.CryptographicException: ASN1 corrupted data..NET System.Security.Cryptographytoken signature is invalid: key is of invalid type: ECDSA verify expects *ecdsa…golang-jwt/jwt (Go)