Fehlermeldung
asn1: structure error: tags don't match
Die vollständige Meldung hängt die erwarteten und gefundenen Tags sowie Kontext zum Feld an, etwa „tags don't match (16 vs {class:0 tag:2 ...}) ... AlgorithmIdentifier @2“. Abgeschnittene Eingaben erzeugen den verwandten Fehler „asn1: syntax error: data truncated“. In aktuellem Go stammt die Meldung aus den Parsern für öffentliche Schlüssel und für PKCS#8; x509.ParseCertificate meldet dieselben Fehler als „x509: malformed certificate“.
Go encoding/asn1 — surfaced through crypto/x509 parsers
Was der Fehler bedeutet
Der DER-Decoder von Go hat ein anderes ASN.1-Tag gefunden, als die Zielstruktur verlangt – du parst einigermaßen gültiges DER in die falsche Go-Struktur oder etwas, das gar kein DER ist. Die Zahlen in der Meldung sind ASN.1-Tags (16 = SEQUENCE, 2 = INTEGER, 13 in einer PEM-Datei = der Bindestrich, mit dem sie beginnt) und zeigen meist genau, was verwechselt wurde.
Warum der Fehler auftritt
PEM-Bytes an einen DER-Parser übergeben
häufigParsePKIXPublicKey, ParsePKCS8PrivateKey und verwandte Funktionen erwarten rohes DER. Der mit Abstand häufigste Auslöser ist PEM-Text (Bindestriche und base64), der ohne vorheriges pem.Decode an sie übergeben wird. (Auch ParseCertificate lehnt PEM-Text ab, mit „x509: malformed certificate“.)
Falscher Parser für den Schlüsselcontainer
häufigEin privater Schlüssel oder ein ganzes Zertifikat, das an ParsePKIXPublicKey übergeben wird – jeder Container hat eine eigene Struktur, und die Tag-Prüfung bemerkt die Verwechslung am ersten abweichenden Feld. Verwechselte Parser für private Schlüssel werden hilfreicher gemeldet: ParseECPrivateKey meldet bei PKCS#8-Bytes „x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)“, und umgekehrt genauso.
Überhaupt kein Zertifikat oder Schlüssel
gelegentlichEine rohe 64-Byte-Signatur, ein JWT oder Framing-Bytes eines Protokolls, die als ASN.1 geparst werden. Beginnt die Eingabe mit etwas anderem als 0x30 (SEQUENCE), akzeptiert sie kein Parser der X.509-Familie.
So behebst du den Fehler
- 1.
Immer zuerst pem.Decode
Extrahiere den DER-Block (und prüfe das Label), bevor du irgendeinen Parser aufrufst.
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.
Container-Parser der Reihe nach ausprobieren
Ist der Container des privaten Schlüssels unbekannt, versuche PKCS#8, dann SEC1, dann PKCS#1 – die übliche Reihenfolge für Schlüssel aus gemischten Quellen.
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.
Die ersten Bytes ansehen
Eine Zeile Hexdump verrät dir, ob du überhaupt DER vor dir hast, und openssl asn1parse zeigt die Struktur, mit der du den gewählten Parser abgleichen kannst.
bash head -c 16 key.der | xxd # 30 81/82 ... → SEQUENCE, plausibly DER openssl asn1parse -inform der -in key.der | head -3