Mensagem de erro
x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)
Também aparece 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)
A função entre parênteses depende do que o Go detectou: `ParsePKCS1PrivateKey`, `ParseECPrivateKey` ou `ParsePKCS8PrivateKey`. O equivalente para chaves públicas é “x509: failed to parse public key (use ParsePKCS1PublicKey instead for this key format)”. Bytes que não correspondem a nenhum dos formatos geram um `asn1: structure error` em vez disso.
Go crypto/x509 — ParsePKCS8PrivateKey / ParsePKCS1PrivateKey / ParseECPrivateKey / ParsePKIXPublicKey
O que significa
Você passou os bytes DER de um formato de chave privada para o parser de outro, e o Go reconheceu em qual formato eles realmente estão. Há três codificações comuns: PKCS#8 (`-----BEGIN PRIVATE KEY-----`, qualquer algoritmo), PKCS#1 (`-----BEGIN RSA PRIVATE KEY-----`, só RSA) e SEC 1 (`-----BEGIN EC PRIVATE KEY-----`, só EC). A dica entre parênteses indica a função que vai analisar seus bytes. A chave em si está correta.
Por que acontece
Chave RSA em PKCS#1, o código espera PKCS#8
comumO `openssl genrsa` (OpenSSL 1.x) e muitas ferramentas antigas gravam `RSA PRIVATE KEY`; código escrito para a saída do `openssl genpkey` chama `ParsePKCS8PrivateKey`. O inverso também acontece com ferramentas mais novas.
Chave EC no formato SEC 1
comumO `openssl ecparam -genkey` grava `EC PRIVATE KEY` (SEC 1, RFC 5915). Essa chave precisa ir para `ParseECPrivateKey` ou ser convertida para PKCS#8.
Chave pública RSA PKCS#1 passada para ParsePKIXPublicKey
ocasional`-----BEGIN RSA PUBLIC KEY-----` é a estrutura PKCS#1 pura, sem o identificador de algoritmo que `PUBLIC KEY` (SPKI) traz.
Como corrigir
- 1.
Escolher o parser pelo tipo PEM
O rótulo PEM indica o formato. Escolha o parser com base em `block.Type` em vez de supor um ú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 as chaves para PKCS#8 e SPKI
PKCS#8 para chaves privadas e SPKI para chaves públicas funcionam com qualquer algoritmo e com qualquer biblioteca moderna. Converta uma vez, no momento do provisionamento.
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
Erros 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)