asn.1 格式学习
作者:互联网
基本概念
抽象语法表示法一(abstract syntax notation one, ASN.1)是支持复杂数据结构和对象的定义、传输、交换的一系列规则。ASN.1是为了支持不同平台的网络通信而设计,与机器架构以及语言实现无关。ASN.1于1988年最先在X.208中定义,最近的更新是在2008年推出的X.680系列文档中。
ASN.1以一种抽象的方式定义数据,如何编码数据则在另外一份标准里面。基本编码规则(basic encoding rules, BER)是第一个数据编码标准。X.509依赖于的唯一编码规则(distinguished encoding rules,DER)是BER的子集,只允许一种方式编码ASN.1的值,这种唯一性对密码学尤其是数字签名的使用非常关键。PEM(privacy-enhancedmail的简写,在此上下文中无含义)是DER使用Base64编码后的ASCII编码格式。
基本语法
类型
给定的ASN.1类型的值是该类型集合的元素。ASN.1有四种类型:简单类型,是“原子的”并且没有任何组件;具有组件的结构化类型;标记类型,从其他类型派生;和其他类型,包括CHOICE类型和ANY类型。可以使用ASN.1赋值运算符::=
给类型和值命名,这些名称可以用于定义其他类型和值。
除CHOICE和ANY外,每种ASN.1类型都有一个标签,该标签由一个类和一个非负标签号组成。当且仅当它们的标签号相同时,ASN.1类型才抽象地相同。换句话说,ASN.1类型的名称不会影响其抽象含义,只有标签会影响它的抽象含义。标签分为四类:
Universal
,用于在所有应用程序中含义相同的类型;这些类型仅在X.208中定义。Application
,用于特定于应用程序的含义的类型,例如X.500目录服务;两个不同应用程序中的类型可能具有相同的特定于应用程序的标签和不同的含义。Private
,用于含义特定于给定企业的类型。Context-specific
,对于其含义特定于给定结构化类型的类型;特定于上下文的标记用于在给定的结构类型的上下文中区分具有相同基础标记的组件类型,并且两种不同结构类型的组件类型可能具有相同的标记和不同的含义。
Type | Tag number(decimal) | Tag number(hexadecimal) |
---|---|---|
INTEGER |
2 | 02 |
BIT STRING |
3 | 03 |
OCTET STRING |
4 | 04 |
NULL |
5 | 05 |
OBJECT IDENTIFIER |
6 | 06 |
SEQUENCE and SEQUENCE OF |
16 | 10 |
SET and SET OF |
17 | 11 |
PrintableString |
19 | 13 |
T61String |
20 | 14 |
IA5String |
22 | 16 |
UTCTime |
23 | 17 |
ASN.1类型和值以灵活的类似于编程语言的表示法表示,并具有以下特殊规则:
- 布局不重要;多个空格和换行符可以视为一个空格。
- 注释由一对连字符
--
或一对连字符和一个换行符分隔。 - 标识符(值和字段的名称)和类型引用(类型的名称)由大小写字母,数字,连字符和空格组成;标识符以小写字母开头;类型引用以大写字母开头。
基本编码规则(BER)
ASN.1的基本编码规则(缩写为BER)提供了一种或多种方法来将任何ASN.1值表示为八位字节串。(当然,还有其他方法可以表示ASN.1值,但BER是在OSI中交换此类值的标准。)
有三种方法可以在BER下编码ASN.1值,其选择取决于值的类型以及值的长度是否已知。这三种方法是
- 原始的定长编码
- 结构化定长编码
- 结构化不定长编码
简单的非字符串类型采用原始的定长方法。结构化类型采用两种结构化方法之一;简单字符串类型可以使用任何方法,具体取决于值的长度是否已知。通过隐式标记派生的类型采用基础类型的方法,通过显式标记派生的类型采用构造的方法。
在每种方法中,BER编码都有三个或四个部分:
- 标识符。这些标识ASN.1值的类和标记号,并指示该方法是原始的还是构造的。
- 长度。对于定长方法,这些方法给出内容八位位组的数量。对于构造的不确定长度的方法,这些表明长度是不确定的。
- 内容。对于原始的定长方法,这些给出了值的具体表示。对于构造的方法,这些方法给出了值成分的BER编码的串联。
- 内容结尾。对于构造的不确定长度方法,这些表示内容的结尾。对于其他方法,则不存在。
原始的定长编码
此方法适用于简单类型以及通过隐式标记从简单类型派生的类型。它要求事先知道值的长度。BER编码的部分如下:
标识符
有两种形式:低标签号(用于0到30之间的标签号)和高标签号(用于31以上的标签号)。
低标签数形式。一八位字节。第8位和第7位指定了类别,第6位的值为0
,表示编码是原始的,第5-1位给出了标记号。
Class | Bit 8 | Bit 7 |
---|---|---|
universal | 0 | 0 |
application | 0 | 1 |
context-specific | 1 | 0 |
private | 1 | 1 |
高标签数形式。两个或更多字节。第一个字节与低标签号格式相同,除了位5-1的值均为1
。第二个和随后的字节给出标签号,以基数128为基数,最高有效位在前,位数越少越好,每个字节的第8位(最后一位除外)设置为1
。
长度
有两种形式:short(对于0到127之间的长度)和long(对于0到2 ^ 1008 -1之间的长度)。
short
,一个字节。位8的值为0
,而位7-1给出长度。long
,2至127个字节。第一个字节的位8的值为1
,而第7-1位给出附加字节的数量。第二个和随后的八位字节以256为基数,以最高有效数字在前。
内容
给出了值的具体表示形式(如果类型是通过隐式标记派生的,则可以给出基础类型的值)
结构化定长编码
标识符
同上,但是第6位是1
长度
同上
内容
值的组成部分的BER编码的串联:
- 对于简单的字符串类型和通过隐式标记从其派生的类型,该值的连续子字符串(隐式标记的基础值)的BER编码的串联。
- 对于结构化类型和通过隐式标记从其派生的类型,值的成分(隐式标记的基础值)的BER编码的串联。
- 对于通过显式标记从任何内容派生的类型,基础值的BER编码。
结构化不定长编码
此方法适用于简单字符串类型,结构化类型,通过隐式标记派生的简单字符串类型和结构化类型的类型,以及通过显式标记派生自任何内容的类型。不需要预先知道值的长度。BER编码的部分如下:
- 标识符。同上。
- 长度。一个字节,
80
- 内容。同上。
- 内容结尾。两个字节
00 00
可分辨编码规则(DER)
ASN.1的可分辨编码规则(缩写为DER)是BER的子集,并给出了一种将任何ASN.1值表示为八位字节字符串的精确方法。
DER在BER中给出的规则中增加了以下限制:
- 当长度在0到127之间时,必须使用简短的长度形式
- 当长度为128或更大时,必须使用长形式的长度,并且长度必须以最少的八位位组数目进行编码。
- 对于简单字符串类型和从简单字符串类型派生的隐式标记类型,必须使用原始的定长方法。
- 对于结构化类型,从结构化类型派生的隐式标记类型和从任何事物派生的显式标记类型,必须使用构造的定长方法。
变量例子
-
BIT STRING
value "011011100101110111"03 04 06 6e 5d c0
DER encoding03 81 04 06 6e 5d c0
long form of length octets23 09 03 03 00 6e 5d 03 02 06 c0
constructed encoding: "0110111001011101" + "11"
-
IA5String
value "test1@rsa.com"16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d
DER encoding16 81 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d
long form of length octets36 13 16 05 74 65 73 74 31 16 01 40 16 07 72 73 61 2e 63 6f 6d
constructed encoding: "test1" + "@" + "rsa.com"
例子
给出了X.501类型Name的ASN.1表示法
Name ::= CHOICE {
RDNSequence }
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
RelativeDistinguishedName ::=
SET OF AttributeValueAssertion
AttributeValueAssertion ::= SEQUENCE {
AttributeType,
AttributeValue }
AttributeType ::= OBJECT IDENTIFIER
AttributeValue ::= ANY
用树型表示就是这样
|-Name CHOICE
|-RDNSequence SEQUENCE OF
|-RelativeDistinguishedName SET OF
|-AttributeValueAssertion SEQUENCE
|-AttributeType OBJECT IDENTIFIER
|-AttributeValue ANY
本节从下至上给出了一个Name类型的值的DER编码示例。
该名称是PKCS示例[Kal93]中测试用户1的名称。该名称由以下路径表示:
(root)
|
countryName = "US"
|
organizationName = "Example Organization"
|
commonName = "Test User 1"
每个级别对应一个RelativeDistinguishedName
值,对于该名称,每个级别都由一个AttributeValueAssertion
值组成。AttributeType
值在等号之前,AttributeValue
值(给定的属性类型打印字符串)是等号后。
countryName
, organizationName
和commonUnitName
是X.520定义的属性类型:
attributeType OBJECT IDENTIFIER ::=
{ joint-iso-ccitt(2) ds(5) 4 }
countryName OBJECT IDENTIFIER ::= { attributeType 6 }
organizationName OBJECT IDENTIFIER ::=
{ attributeType 10 }
commonUnitName OBJECT IDENTIFIER ::=
{ attributeType 3 }
-
AttributeType
上述 countryName, organizationName, commonName 的值均为 OCTET STRING. 因此他们的 DER 编码方法应该为 primitive, definite-length. 对于 OBJECT IDENTIFIER 类型, Identifier 字段应该为 06. bit8 和 bit7 为 0, 代表 Universal class06 03 55 04 06 countryName 06 03 55 04 0a organizationName 06 03 55 04 03 commonName
-
AttributeValue
假设上述 countryName, organizationName, commonName 属性的值类型均为 PrintableString, 且值分别为 “US”, “Example Organization”, “Test User 1”.
编码结果分别为:13 02 55 53 // "US" 13 14 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 74 69 6f 6e // "Example Organization" 13 0b 54 65 73 74 20 55 73 65 72 20 31 // "Test User 1"
-
AttributeValueAssertion
30 09 // countryName = "US" 06 03 55 04 06 13 02 55 53 30 1b // organizationName = "Example Organization" 06 03 55 04 0a 13 14 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 74 69 6f 6e 30 12 // commonName = "Test User 1" 06 03 55 04 0b 13 0b 54 65 73 74 20 55 73 65 72 20 31
-
RelativeDistinguishedName
31 0b 30 09 ... 55 53 31 1d 30 1b ... 6f 6e 31 14 30 12 ... 20 31
-
RDNSequence
30 42 31 0b ... 55 53 31 1d ... 6f 6e 31 14 ... 20 31
-
Name
CHOICE相当于联合体,所以和RDNSequence一样30 42 31 0b 30 09 06 03 55 04 06 // attributeType = countryName 13 02 55 53 // attributeValue = "US" 31 1d 30 1b 06 03 55 04 0a // attributeType = organizationName 13 14 45 78 61 6d 70 6c 65 20 4f 72 67 67 61 6e 69 7a 61 74 69 6f 6e // attributeValue = "Example Organization" 31 14 30 12 06 03 55 04 03 // attributeType = commonName 13 0b 54 65 73 74 20 55 73 65 72 20 31 // attributeValue = "Test User 1"
把数据放到文件中,去在线asn.1解析,成功解析
参考链接
A Layman's Guide to a Subset of ASN.1, BER, and DER
ASN.1 学习
ASN.1 JavaScript decoder
标签:编码,03,asn.1,31,学习,ASN.1,类型,格式,BER 来源: https://www.cnblogs.com/20175211lyz/p/12722360.html