跳到主要内容
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 就能看出手里的到底是不是 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

相关错误

浏览完整的签名错误库