Saltar al contenido
ecdsa.com
Go crypto/x509Go

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

Cómo solucionarlo

  1. 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. 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

Explorar toda la base de datos de errores de firma