听起来您需要介绍 ASN.1 标记。有两个角度可以解决这个问题。X.690 定义了 BER/CER/DER 编码规则。因此,它回答了标签如何编码的问题。X.680 定义了 ASN.1 本身。因此,它定义了标记的语法和规则。这两个规范都可以在 ITU-T 网站上找到。我会给你一个快速的概述。
BER/DER/CER 中使用标签来识别类型。它们对于区分 SEQUENCE 的组件和 CHOICE 的替代项特别有用。
标签结合了标签类别和标签编号。标记类是 UNIVERSAL、APPLICATION、PRIVATE 和 CONTEXT-SPECIFIC。UNIVERSAL 类基本上用于内置类型。APPLICATION 通常用于用户定义的类型。CONTEXT-SPECIFIC 通常用于构造类型(SEQUENCE、CHOICE、SEQUENCE OF)内的组件。在语法上,当在 ASN.1 模块中指定标签时,它们会写在括号内:[ tag_class tag_number ]; 对于 CONTEXT-SPECIFIC,tag_class 被省略。因此,[应用程序 10] 或 [0]。
虽然每个 ASN.1 类型都有一个关联的标签,但从句法上讲,还有一个“TaggedType”,ASN.1 作者使用它来指定用于编码类型的标签。基本上,TaggedType 将标签前缀放在类型之前。例如:
MyType ::= SEQUENCE {
field_with_tagged_type [0] UTF8String
}
TaggedType 中的标记是显式的或隐式的。如果是显式的,这意味着我希望对原始标签进行显式编码。如果是隐式的,这意味着我很高兴只对我指定的标签进行编码。在显式情况下,BER 编码产生一个嵌套的 TLV(标签长度值):外部标签(上例中的 [0])、长度,然后是另一个 TLV 作为值。在示例中,此内部 TLV 将具有用于 UTF8String 的 [UNIVERSAL 12] 标记。
标记是显式的还是隐式的取决于您如何编写标记和标记环境。例如:
MyType2 ::= SEQUENCE {
field_with_explicit_tag [0] EXPLICIT UTF8String OPTIONAL,
field_with_implicit_tag [1] IMPLICIT UTF8String OPTIONAL,
field_with_tag [2] UTF8String OPTIONAL
}
如果您既未指定 IMPLICIT 也未指定 EXPLICIT,则有一些规则定义标记是显式还是隐式(参见 X.680 31)。这些规则考虑了为 ASN.1 模块定义的标记环境。ASN.1 模块可以将标记环境指定为隐式标记、显式标记或自动标记。 粗略地说,如果您没有为标记指定 IMPLICIT 或 EXPLICIT,则如果标记环境为 EXPLICIT,则标记将是显式的,如果标记环境是 IMPLICIT 或 AUTOMATIC,则标记将是隐式的。自动标记环境与 IMPLICIT 标记环境基本相同,除了自动为 SEQUENCE 和 CHOICE 类型的成员分配唯一标记。
请注意,在上面的示例中,MyType2 的三个组件都是可选的。在 BER/CER/DER 中,解码器将根据编码标签(显然最好是唯一的)知道存在什么组件。