TBSCertificate ::= SEQUENCE {
version [0] Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
extensions [3] Extensions OPTIONAL
-- If present, version MUST be v3 --
}
以上编码方括号中指定的是自定义tag,那为什么要指定自定义tag呢?
在一个Sequence复合数据结构中,各个子字段的函义完全是由在sequence中出现的顺序决定的。如果所有字段都是固定的,这没有什么问题。但是如果出现可选字段,顺序就会打乱。所以对于可选字段就不能单纯依靠字段顺序进行解析,这时候自定义tag就派上用场了,字段的函义由tag来决定。
ASN.1为自定义tag当义了两种编码方式。在IMPLICIT编码方式中自定义tag会替换原始的tag,优点是不会增加额外的存储空间,但是原始字段的tag就丢掉了,这样要确定字段的数据类型就需要联系上下文来推断。另一种是EXPLICIT编码,这种方式会创建一个squence然后原始字段会成为这个squence的唯一字段,自定义的tag是这个squence的tag,缺点是新创建的squence会额外占用两个字节。
两种编码的具体示例可以在这里找到:
https://letsencrypt.org/zh-cn/docs/a-warm-welcome-to-asn1-and-der/#explicit-%E4%B8%8E-implicit
其中EXPLICIT编码是默认的编码方式。