ASN.1完全教程:抽象语法记法1编码规则详解
目录
一、ASN.1是什么
ASN.1(Abstract Syntax Notation One,抽象语法记法1)是一种由ITU-T(国际电信联盟电信标准分局)和ISO/IEC联合标准化的数据描述语言。ASN.1提供了一套独立于平台和编程语言的语法规则,用于定义数据结构(类型)及数据的编码规则。
简单说,ASN.1是什么?它由两部分组成:
- ASN.1语法(ITU-T X.680系列):用类似编程语言结构体的语法定义数据类型(Schema层)
- ASN.1编码规则(ITU-T X.690系列):将定义好的数据编码为比特流/字节流(Encoding层)
这种语法与编码分离的设计使得ASN.1可以定义一次数据结构,然后根据场景选择不同的编码方式:带宽敏感时用紧凑的PER编码,需要互操作时用标准的BER/DER编码。
ASN.1几乎无处不在——每个HTTPS连接背后、每张智能卡、每个电子签名都离不开它:
- X.509证书:用ASN.1 DER编码
- PKCS系列(PKCS#1/#7/#8/#10/#12/#15):全部基于ASN.1
- LDAP协议:使用ASN.1 BER
- SNMP协议:基于ASN.1
- 4G/5G信令:3GPP RRC/NAS消息使用ASN.1 PER
- ISO7816-15:加密信息应用基于ASN.1 + PKCS#15
二、ASN.1历史与发展
ASN.1最早于1984年由ITU-T发布(作为X.409标准),最初是为了解决X.400电子邮件系统和X.500目录服务中跨平台数据交换的问题。1994年发布了ASN.1完整规范(X.680~X.695系列),此后不断扩展新的类型和编码规则。
| 时间 | 标准 | 里程碑 |
|---|---|---|
| 1984 | X.409 | ASN.1首次发布 |
| 1994 | X.680~X.695 | ASN.1完整规范(1994版) |
| 2002 | X.693 (XER)、X.691 (PER) | 新增XML编码规则和紧凑包编码规则 |
| 2015 | X.696 (OER)、X.697 (JER) | 新增八位组编码规则和JSON编码规则 |
| 2021 | X.680系列第7版 | 最新修订版 |
三、ASN.1语法基础
ASN.1语法的核心是类型定义(Type Assignment)和值定义(Value Assignment)。ASN.1模块(Module)是代码组织的基本单元。
-- ASN.1模块定义示例
MyModule DEFINITIONS AUTOMATIC TAGS ::= BEGIN
-- 简单类型定义
Age ::= INTEGER (0..150)
Name ::= UTF8String (SIZE (1..64))
Active ::= BOOLEAN
-- 复合类型定义
Person ::= SEQUENCE {
name Name,
age Age,
isActive Active DEFAULT TRUE,
email IA5String OPTIONAL
}
-- CHOICE类型(枚举不同结构)
PaymentMethod ::= CHOICE {
creditCard CreditCardInfo,
debitCard DebitCardInfo,
cash NULL
}
CreditCardInfo ::= SEQUENCE {
pan NumericString (SIZE (16..19)),
expiryDate NumericString (SIZE (4)),
cvv NumericString (SIZE (3))
}
DebitCardInfo ::= SEQUENCE {
pan NumericString (SIZE (16..19)),
bankCode NumericString (SIZE (8))
}
END
四、ASN.1数据类型大全
ASN.1类型体系分为简单类型(Primitive Types)和构造类型(Constructed Types)两大类:
常用简单类型
| ASN.1类型 | Tag (Universal) | 说明 | 典型用途 |
|---|---|---|---|
| BOOLEAN | 0x01 | 布尔值(TRUE/FALSE) | 标志位 |
| INTEGER | 0x02 | 任意精度整数 | 序列号、版本号、RSA模数 |
| BIT STRING | 0x03 | 比特串(任意长度) | 公钥编码、签名值 |
| OCTET STRING | 0x04 | 字节串 | 证书指纹、对称密钥 |
| NULL | 0x05 | 空值 | 算法参数占位 |
| OBJECT IDENTIFIER | 0x06 | 对象标识符(OID) | 算法标识、策略标识、扩展标识 |
| UTF8String | 0x0C | UTF-8字符串 | 证书主题/颁发者名称 |
| PrintableString | 0x13 | 可打印ASCII字符 | 传统证书中的名称字段 |
| IA5String | 0x16 | IA5/ASCII字符串 | 电子邮件地址、DNS名称 |
| UTCTime | 0x17 | UTC时间(YYMMDDHHMMSSZ) | 证书有效期(2049年之前) |
| GeneralizedTime | 0x18 | 通用时间(YYYYMMDDHHMMSSZ) | 证书有效期(2049年后) |
| NumericString | 0x12 | 数字字符串(0-9+空格) | 电话号码、PAN卡号 |
构造类型
| ASN.1类型 | Tag (Universal) | 说明 |
|---|---|---|
| SEQUENCE | 0x30 | 有序结构体(最重要!X.509证书的主体结构) |
| SEQUENCE OF | 0x30 | 有序列表(同类型元素的数组) |
| SET | 0x31 | 无序集合(元素顺序无关) |
| SET OF | 0x31 | 无序集合列表 |
| CHOICE | 无固定Tag | 联合体(多选一) |
五、ASN.1编码规则
ASN.1编码规则定义了如何将ASN.1定义的数据类型编码为二进制字节流。主要有以下几种:
| 编码规则 | 标准 | 特点 | 典型应用 |
|---|---|---|---|
| BER (Basic Encoding Rules) | X.690 | TLV结构,编码灵活,允许多种合法编码 | LDAP、SNMP、实时协议 |
| CER (Canonical Encoding Rules) | X.690 | BER的规范子集,消除歧义,适合流式大数据 | 大文件签名 |
| DER (Distinguished Encoding Rules) | X.690 | BER的严格子集,每个值只有一种合法编码 | X.509证书、PKCS签名、智能卡 |
| PER (Packed Encoding Rules) | X.691 | 极致紧凑,省略Tag和Length,需要Schema解码 | 4G/5G信令(3GPP) |
| OER (Octet Encoding Rules) | X.696 | 面向字节的紧凑编码,编解码速度快 | IoT设备 |
| JER (JSON Encoding Rules) | X.697 | 将ASN.1数据编码为JSON格式 | Web API、REST接口 |
| XER (XML Encoding Rules) | X.693 | 将ASN.1数据编码为XML格式 | SOAP/XML Web服务 |
六、BER与DER编码详解
BER编码和DER编码是最重要的两种ASN.1编码规则,它们都使用TLV格式(Tag-Length-Value)。
BER/DER的Tag-Value-Length结构
BER/DER编码 = Identifier Octets + Length Octets + Contents Octets
= Tag (1~N字节) + Length (1~N) + Value (变长)
Identifier Octets(Tag)编码:
Tag首字节 = b8 b7 b6 b5 b4 b3 b2 b1
b8-b7: Class (00=Universal, 01=Application, 10=Context-specific, 11=Private)
b6: Form (0=Primitive, 1=Constructed)
b5-b1: Tag Number (0~30=直接, 31=多字节扩展)
BER vs DER关键区别
DER是BER的确定性(Distinguished)子集。BER编码允许同一数据有多种合法编码方式(如BOOLEAN的TRUE可以是任何非零字节),而DER编码严格规定每种数据只有一种编码方式(BOOLEAN TRUE必须是0xFF)。
| 编码选择 | BER允许 | DER要求 |
|---|---|---|
| BOOLEAN TRUE | 任意非0字节 | 必须为 0xFF |
| BOOLEAN FALSE | 任意0x00~0xFF | 必须为 0x00 |
| Length编码 | 短格式或长格式均可 | 必须使用最短格式 |
| BIT STRING多余位 | 可任意 | 必须全部为0 |
| SET元素顺序 | 任意 | 必须按DER编码升序 |
| INTEGER编码 | 可以有多余前导零 | 不能有前导零(除符号位) |
为什么DER很重要?
在数字签名场景中,签名是针对数据的字节序列计算的。如果同一数据有两种合法编码,签名就不唯一。因此DER编码是X.509证书和PKCS签名的唯一定编码方式——客户端验证证书签名时,必须使用与签发时完全一致的DER字节序列。
七、OBJECT IDENTIFIER(OID)详解
OID(对象标识符)是ASN.1的核心概念之一。ASN.1 OID是一个全球唯一的层次化编号,以点分十进制表示,如1.2.840.113549.1.1.11(sha256WithRSAEncryption签名算法)。
# OID树结构(部分)
1 (iso)
├── 1.2 (member-body)
│ └── 1.2.840 (us)
│ └── 1.2.840.113549 (rsadsi — RSA Data Security Inc.)
│ ├── 1.2.840.113549.1 (PKCS)
│ │ ├── 1.2.840.113549.1.1 (PKCS#1 — RSA)
│ │ │ ├── .1 = rsaEncryption
│ │ │ ├── .11 = sha256WithRSAEncryption
│ │ │ └── .14 = sha224WithRSAEncryption
│ │ ├── 1.2.840.113549.1.7 (PKCS#7)
│ │ └── 1.2.840.113549.1.9 (PKCS#9)
│ └── 1.2.840.113549.2 (Digest Algorithms)
│
├── 1.3.14.3.2.26 = sha1 (NIST)
├── 2.5.4.3 = commonName (X.500 attribute types)
├── 2.5.29.14 = subjectKeyIdentifier (X.509 extension)
└── 2.16.840.1.101.3.4.2.1 = sha256 (NIST)
八、ASN.1与X.509证书
X.509证书是ASN.1最广为人知的应用。每个HTTPS网站使用的TLS/SSL证书就是一个ASN.1 DER编码的X.509结构。
-- X.509证书的ASN.1简化定义
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING
}
TBSCertificate ::= SEQUENCE {
version [0] INTEGER DEFAULT v1 (0),
serialNumber INTEGER,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
extensions [3] Extensions OPTIONAL
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
九、ASN.1与PKCS标准
PKCS(Public-Key Cryptography Standards,公钥密码学标准)系列由RSA公司发布,几乎所有PKCS标准都使用ASN.1定义和DER编码。
| 标准 | 内容 | ASN.1使用 |
|---|---|---|
| PKCS#1 | RSA加密和签名 | RSA公钥/私钥的ASN.1结构定义 |
| PKCS#7 | 加密消息语法(CMS) | SignedData、EnvelopedData的ASN.1定义 |
| PKCS#8 | 私钥信息语法 | PrivateKeyInfo/EncryptedPrivateKeyInfo的ASN.1结构 |
| PKCS#10 | 证书请求(CSR) | CertificationRequest的ASN.1定义 |
| PKCS#11 | 加密令牌接口(Cryptoki) | 属性值的ASN.1 DER编码 |
| PKCS#12 | 个人信息交换(PFX/P12) | PFX结构的ASN.1定义 |
十、ASN.1在智能卡中的应用
在智能卡领域,ASN.1主要用于以下场景:
- ISO7816-15:加密信息应用,使用ASN.1 + PKCS#15描述卡内加密对象的存储结构(证书、私钥、PIN等)
- EMV规范:部分数据对象(如公钥证书)使用ASN.1 DER编码,尽管大多数EMV TLV数据使用的是简化版BER-TLV
- 电子身份证(eID):CEN/TS 15480标准使用ASN.1描述公民卡数据结构
- 电子护照(ICAO 9303):护照芯片中的DG(Data Group)使用ASN.1 DER编码
延伸阅读
关于智能卡TLV编码的详细内容,参见TLV格式详解;关于EMV支付标签数据,参见EMV Tag详解;关于ISO7816-15加密信息应用,参见ISO7816完整教程。
十一、ASN.1与TLV的关系
ASN.1和TLV的关系可以理解为:
- ASN.1是类型定义语言(描述"这是什么")
- BER/DER是TLV编码规则(描述"怎么编码")
- TLV格式(Tag-Length-Value)是BER/DER的底层编码结构
换句话说,ASN.1 TLV可以理解为:ASN.1定义数据类型(schema层),BER/DER定义了如何将类型实例编码为TLV字节流(encoding层)。EMV TLV则不同——它不使用ASN.1 schema,而是直接将语义编码在Tag值中(如Tag 0x5A直接表示"这是PAN")。
十二、ASN.1开发工具与在线解析
实际开发中常用的ASN.1工具:
- OpenSSL asn1parse:
openssl asn1parse -in cert.der -inform DER解析DER编码的证书和PKCS文件 - 在线ASN.1解析器:将十六进制DER数据粘贴到在线工具,可视化SEQUENCE/SET/OID层次结构
- ASN.1编译器(如asn1c):从ASN.1 schema自动生成C/Java/Python的编解码代码
- dumpasn1:开源的命令行ASN.1对象查看器
# OpenSSL 解析 X.509 证书的 ASN.1 结构
$ openssl x509 -in certificate.pem -text -noout
# 解析私钥的 PKCS#8 ASN.1 结构
$ openssl asn1parse -in private.key -inform PEM
# 典型输出(部分):
# 0:d=0 hl=4 l= 968 cons: SEQUENCE
# 4:d=1 hl=2 l= 1 prim: INTEGER :00
# 7:d=1 hl=2 l= 13 cons: SEQUENCE
# 9:d=2 hl=2 l= 9 prim: OBJECT IDENTIFIER :sha256WithRSAEncryption
学习路径
ASN.1是安全通信和数据编码的理论基础。推荐学习路径:ISO7816完整教程(智能卡基础)→ TLV格式详解(编码基础)→ ASN.1完全教程(本文,理论进阶)→ EMV Tag详解(实战应用)。