本文へスキップ
ecdsa.com
Go encoding/asn1Go

エラーメッセージ

asn1: structure error: tags don't match

完全なメッセージには、期待されたタグと検出されたタグに加えてフィールドの情報も付きます。例:「tags don't match (16 vs {class:0 tag:2 ...}) ... AlgorithmIdentifier @2」。入力が途中で切れている場合は、関連する別のエラー「asn1: syntax error: data truncated」になります。現在の Go では、このメッセージは公開鍵用と PKCS#8 用のパーサーから出力されます。x509.ParseCertificate は、同じ誤りを「x509: malformed certificate」として報告します。

Go encoding/asn1 — surfaced through crypto/x509 parsers

このエラーの意味

Go の DER デコーダーが、変換先の構造体が必要とするものとは異なる ASN.1 タグを検出しました。おおむね正しい DER を間違った Go の構造体にパースしているか、そもそも DER ではないものをパースしています。メッセージ中の数値は ASN.1 タグで(16 = SEQUENCE、2 = INTEGER、PEM ファイルなら 13 = 先頭のダッシュ)、たいていは何を取り違えたのかを正確に示しています。

発生する理由

修正方法

  1. 1.

    必ず先に pem.Decode を通す

    パーサーを呼び出す前に、DER ブロックを取り出して(ラベルも確認して)ください。

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

    コンテナーのパーサーを順番に試す

    秘密鍵のコンテナーがわからない場合は、PKCS#8、SEC1、PKCS#1 の順に試してください。出どころの異なる鍵を扱うときの標準的な切り分け手順です。

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

    先頭のバイトを確認する

    hexdump の 1 行を見れば、そもそも DER なのかどうかがわかります。また、openssl asn1parse で構造を表示すれば、選んだパーサーと照らし合わせられます。

    bash
    head -c 16 key.der | xxd          # 30 81/82 ... → SEQUENCE, plausibly DER
    openssl asn1parse -inform der -in key.der | head -3

関連するエラー

署名エラーデータベースをすべて見る