ASN.1

简单介绍

ASN.1 (Abstract Syntax Notation dot one) ,用来描述通信协议中传输的数据,定义了抽象数据类型规范的形式, 具有健壮性, 准确性, 独立于编程语言,独立于硬件和操作系统, 可以通过简单类型组成复杂的数据类型。

例如定义联系人 Contact 类型的语法

1
2
3
4
Contact ::= SEQUENCE {
name VisibleString,
phone NumericString
}

上述的例子中定义了一个联系人的结构, 具有这样结构的联系人 name = ‘Josn Smith’, phone = 987 6543210可以通过 AS1.1 的编码规则 (后面会讲到) 序列化为二进制或文本格式, 便于进行传输

1
2
        JSON Encoding Rules (JER)  
{ "name" : "John Smith", "phone" : "987 6543210" }

完整定义的示例

购买订单类型的 ASN.1 定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
-- 所有的定义都需要包含在一个模块(module)中, module 是以 'BEGIN' 关键字开始, 'END' 关键字结束
-- ASN.1 中一个 Tag 是消息中每个组件的一个内部标识符(internal identification). Tag 都是唯一的, 可以直接指定,但最好还是使用 AUTOMATIC TAGS, 易于阅读和理解, 较少歧义性和冲突性的可能

MyShopPurchaseOrders DEFINITIONS AUTOMATIC TAGS ::= BEGIN

PurchaseOrder ::= SEQUENCE {
dateOfOrder DATE,
customer CustomerInfo,
items ListOfItems
}

CustomerInfo ::= SEQUENCE {
companyName VisibleString (SIZE (3..50)),
billingAddress Address,
contactPhone NumericString (SIZE (7..12))
}

Address::= SEQUENCE {
street VisibleString (SIZE (5 .. 50)) OPTIONAL,
city VisibleString (SIZE (2..30)),
state VisibleString (SIZE(2) ^ FROM ("A".."Z")),
zipCode NumericString (SIZE(5 | 9))
}

ListOfItems ::= SEQUENCE (SIZE (1..100)) OF Item

Item ::= SEQUENCE {
itemCode INTEGER (1..99999),
color VisibleString ("Black" | "Blue" | "Brown"),
power INTEGER (110 | 220),
deliveryTime INTEGER (8..12 | 14..19),
quantity INTEGER (1..1000),
unitPrice REAL (1.00 .. 9999.00),
isTaxable BOOLEAN
}
END

ASN.1 基础数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
-- BOOLEAN
doorOpen BOOLEAN ::= TRUE

-- INTEGER
speed INTEGER (0..60) ::= 40

--VisibleString
LineOfText ::= VisibleString

--IA5String
TextWithLayout ::= IA5String

--MORE ARE NOT LISTED HERE

Most Common ASN.1 Types

Constaints 约束

ASN.1 的 schema 定义中可以包含约束, 用来限制给定字段或类型的有效值集合, 通过使用约束, 也可以生成一个更紧凑的编码, 例如 INTEGER(0..200) 的值用一个字节进行编码就够了

基础约束

字母表约束

1
ardToReadChars ::= IA5String (FROM("8BI10OD5S"))

模式(类似于正则表达式)

1
LicensePlate ::= IA5String (PATTERN "[0-9]#4(-[A-Z]#2)?") -- NNNN[-NN]

值的大小,长度约束

1
2
LicensePlate ::= IA5String (SIZE (4..7))
CarPark ::= SEQUENCE SIZE (1..25) OF LicensePlate

值取值范围约束

1
CarSpeed ::= INTEGER (0..200)

单值约束

1
2
3
4
WarningColors ::= UTF8String ("Red" | "Yellow")
InfoColors ::= UTF8String ("Blue" | "White")
CitySpeedLimit ::= INTEGER (25 | 30 | 40)
HighwaySpeedLimit ::= INTEGER (40 | 50 | 60 | 70)

包含子类型

1
2
3
SignColors ::= UTF8String (InfoColors UNION WarningColors)
SpeedLimitSigns ::= INTEGER (CitySpeedLimit | HighwaySpeedLimit | 10 | 65)
RuralSpeedLimit ::= INTEGER (CitySpeedLimit INTERSECTION HighwaySpeedLimit)

编码约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PerInside ::= OCTET STRING (
CONTAINING Doc
ENCODED BY { joint-iso-itu-t asn1(1)
packed-encoding(3)
basic(0)
unaligned(1)})

pdf OBJECT IDENTIFIER ::= { iso(1)
member-body(2)
us(840)
adobe(113583)
acrobat(1)}

Doc ::= OCTET STRING (ENCODED BY pdf)

更复杂的字段条件依赖约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Schema DEFINITIONS AUTOMATIC TAGS ::= BEGIN

Address ::= SEQUENCE {
street-address UTF8String,
country UTF8String -- see a note below,
postal-code UTF8String
} ((WITH COMPONENTS {
...,
country ("USA"),
postal-code (PATTERN "[0-9]#5(-[0-9]#4)?")
}
| WITH COMPONENTS {
...,
country ("Canada"),
postal-code (PATTERN "[0-9][A-Z][0-9]
[A-Z][0-9][A-Z]")
}
| WITH COMPONENTS {
...,
country ("Netherlands"),
postal-code (PATTERN "[0-9]#4 [A-Z]#2")
}
))

END

Encoding Rules - 编码规则

编码规则描述了应该将 ASN.1 中定义的值如何进行编码以进行传输(被转换为字节进行传输,或者反之,将字节转为 ASN.1 中的值) ,并且不受机器,编程语言,应用程序表示的影响。每一种编码规则都有其特点,例如在压缩方面的,解码速度方面的。任何一种编码规则都能表示要进行交换的信息,只是使用场景不同

BER, DER, CER

BER (Basic Encoding Rules) 是最古老的编码规则,使用 TLV (Tag-Length-Value) 的格式对所有的信息进行编码,即先发送一个标签(Tag)表明数据的类型,如 SEQUENCE,接着是数据的长度(Length), 然年后是实际的数据,DER (Distinguished Encoding Rules) 以及 CER (Canonical Encoding Rules) 是 BER 的子集,消除了 BER 提供的一些灵活性。DER 通常使用在于安全相关的应用中,例如 X.509 数字证书。

OER

OER (Octet Encoding Rules) - 最快的 ASN.1 编码规则,与 PER (Packed Encoding Rules) 一样,通过利用 ASN.1 的 schema 的信息表示的优势来限制包含类每个编码消息的信息数量,生成紧凑的编码输出。聚焦于编码与解码的速度。

PER

PER (Packed Encoding Rules) 最紧凑的编码规则,与 BER 不同的是,PER 不会发送 TLV 中的标签 T, 是应为消息中的组件的顺序是一致的,如果 TLV 中的值 V 是大小固定的,也不会发送长度 L. PER 同样使用的 ASN.1 定义之外的的信息来减少冗余的数据(V). 因此,PER 编码的消息更加紧凑,能够节省带宽.

XER,E-XER

XER (XML Encodind Rules), E-XER(Extended XER) 使用 XML 文本格式来进行编码, 格式为 <start-tag> value <end-tag>. XER 与 E-XER 的区别在于 E-XER 生成的默认编码更适合与 XSD(XML Schema Definition) 引擎进行信息交换. 相同的 ASN.1 数据可以使用多个编码规则, 这意味着来自于手机的 PER 编码的消息可以转换为 E-XER 编码, 用于在一个 web 浏览器中进行展示和操作

JER

JER (JSON Encoding Rules), 基于 JSON 格式的编码规则, 相比 XER, E-XER, 更加紧凑, 易于使用. 基于 RFC-7159 中的 JSON 规范.

通过JER,ASN.1用户可以轻松调试ASN.1协议并进行故障排除.

参考文献

[1] What is ASN1

[2] ASN.1简介及OpenSSL中ASN.1接口使用举例

[3] openssl 密钥生成和解析