Mensaje de error
asn1: structure error: tags don't match
El mensaje completo añade las etiquetas esperada y encontrada, más el contexto del campo, por ejemplo «tags don't match (16 vs {class:0 tag:2 ...}) ... AlgorithmIdentifier @2». Las entradas truncadas producen el error hermano «asn1: syntax error: data truncated». En las versiones actuales de Go, el mensaje procede de los analizadores de claves públicas y de PKCS#8; x509.ParseCertificate notifica los mismos errores como «x509: malformed certificate».
Go encoding/asn1 — surfaced through crypto/x509 parsers
Qué significa
El decodificador DER de Go encontró una etiqueta ASN.1 distinta de la que requiere la estructura de destino: estás analizando DER más o menos válido con la estructura de Go equivocada, o analizando algo que ni siquiera es DER. Los números del mensaje son etiquetas ASN.1 (16 = SEQUENCE, 2 = INTEGER, 13 en un archivo PEM = el guion con el que empieza), y suelen identificar la confusión con precisión.
Por qué ocurre
Bytes PEM pasados a un analizador DER
frecuenteParsePKIXPublicKey, ParsePKCS8PrivateKey y compañía reciben DER binario. Pasarles texto PEM (guiones y base64) sin aplicar antes pem.Decode es, con diferencia, la causa más frecuente. (ParseCertificate también rechaza el texto PEM, con «x509: malformed certificate»).
Analizador equivocado para el contenedor de la clave
frecuenteUna clave privada o un certificado completo pasados a ParsePKIXPublicKey: cada contenedor tiene una estructura distinta, y la comprobación de etiquetas detecta el cambio en el primer campo que diverge. Confundir los analizadores de claves privadas da un mensaje más útil: ParseECPrivateKey con bytes PKCS#8 dice «x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)», y viceversa.
Ni siquiera es un certificado o una clave
ocasionalUna firma raw de 64 bytes, un JWT o bytes del entramado de un protocolo analizados como ASN.1. Si la entrada empieza por cualquier cosa que no sea 0x30 (SEQUENCE), ningún analizador de la familia X.509 la aceptará.
Cómo solucionarlo
- 1.
Aplicar siempre pem.Decode primero
Extrae el bloque DER (y comprueba su etiqueta) antes de llamar a cualquier analizador.
go block, _ := pem.Decode(pemBytes) if block == nil { return fmt.Errorf("input is not PEM") } cert, err := x509.ParseCertificate(block.Bytes) // block.Type == "CERTIFICATE" - 2.
Probar los analizadores de contenedores en orden
Si no conoces el contenedor de la clave privada, prueba PKCS#8, después SEC1 y después PKCS#1: es el procedimiento estándar para claves de orígenes diversos.
go if k, err := x509.ParsePKCS8PrivateKey(der); err == nil { return k, nil } if k, err := x509.ParseECPrivateKey(der); err == nil { return k, nil } if k, err := x509.ParsePKCS1PrivateKey(der); err == nil { return k, nil } return nil, errors.New("unrecognized private key format") - 3.
Mirar los primeros bytes
Una línea de volcado hexadecimal te dice si al menos tienes DER, y openssl asn1parse muestra la estructura que debe coincidir con el analizador elegido.
bash head -c 16 key.der | xxd # 30 81/82 ... → SEQUENCE, plausibly DER openssl asn1parse -inform der -in key.der | head -3