写点什么

密码学系列之:ASN.1 接口描述语言详解

作者:程序那些事
  • 2022 年 5 月 27 日
  • 本文字数:2560 字

    阅读完需:约 8 分钟

密码学系列之:ASN.1接口描述语言详解

简介

ASN.1 是一种跨平台的数据序列化的接口描述语言。可能很多人没有听说过 ASN.1, 但是相信有过跨平台编程经验的同学可能都听过 protocol buffers 和 Apache Thrift,虽然 ASN.1 和上面两个语言相比不是那么出名,但是 ASN.1 的出现要比他们早的多,早在 1984 年 ASN.1 就出现了。


和他们相比 ASN.1 并没有提供单一的开源实现,而是作为一种规范来供第三方供应商实现的。ASN.1 主要用在定义各种基础协议中,比如常用的 LDAP,PKCS,GSM,X.500 等。


ASN.1 是一种和平台、语言无关的描述语言,可以使用很多 ASN.1 的翻译工具,将 ASN.1 翻译成为 C, C++, Java 等代码。

ASN.1 的例子

既然 ASN.1 是一个描述语言,那么我们先来看一个直观的例子。ASN.1 的基础是 module, 我们看一下 ASN.1 中 module 的例子:


StudentCards DEFINITIONS AUTOMATIC TAGS ::= BEGIN
StudentCard ::= SEQUENCE {dateOfBirthday DATE,student StudentInfo}
StudentInfo ::= SEQUENCE {studentName VisibleString (SIZE (3..50)),homeAddress 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))}
END
复制代码


上面的例子中,我们使用 ASN.1 定义了一个 StudentCard,最外层的以 BEGIN 和 END 包围的就是 module。StudentCards 是 module 的名字,首字母必须大写。


其中::= 是一个赋值符号。


module 中可以有多个 type, type 的名字也必须首字母大写,例如上面的 StudentCard,StudentInfo 等等。


每个 type 中定义了它的组成组件,组件的名字首字母必须小写,这些组件的名字又叫做 identifiers。


上面的 dateOfBirthday 后面接的 DATE 是 ASN.1 中内置的类型。而 student 后面的 StudentInfo 是一个自定义类型,并且同样包含在 module 中。


StudentInfo 中的 studentName 是一个 VisibleString,这个 String 的限制是 size 在 3 到 50 之间。


上面我们定义 module 的时候在 module 后面加上了AUTOMATIC TAGS,这是什么意思呢?


在 ASN.1 中,tags 是 ASN.1 消息中每个组件的内部标识符,以 Address 为例,我们希望给 Address 中的每个属性都指定一个内部的标识符,如下所示:


Address::= SEQUENCE {street  [0] VisibleString (SIZE (5 .. 50)) OPTIONAL,city    [1] VisibleString (SIZE (2..30)),state   [2] VisibleString (SIZE(2) ^ FROM ("A".."Z")),zipCode [3] NumericString (SIZE(5 | 9))}
复制代码


这里面的[0] [1] 就是标识符,当然,我们可以在定义 module 的时候手动指定这些 tags,但是如果我们使用AUTOMATIC TAGS,这些标识符会自动创建,从而避免了手动创建标识符可能带来的问题。

ASN.1 中的内置类型

通过上面的讲解,我们对 ASN.1 有了一个基本的概念。如果想要对 ASN.1 进行更加深入的研究,那么我们首先要知道 ASN.1 中的内置类型。


一般来说 ASN.1 中有下面的数据类型:


  • BOOLEAN


BOOLEAN 和编程语言中的布尔值是一致的,它有两个可能得值:TRUE 和 FALSE。下面是具体而用法:


removed BOOLEAN ::= TRUE
复制代码


  • INTEGER


INTEGER 表示的是一个整数,如下所示,表示的是一个年例范围是 0 到 100,最终的取值是 18:


age INTEGER (0..100) ::= 18
复制代码


  • BIT STRING


字节的位表示方法,可以给一个 byte 中的每一个 bit 进行设值:


Status ::= BIT STRING {married(0),handsome(1),kind(2)}myStatus Status ::= {handsome, kind}
复制代码


上面的例子中,我们设置了 Status,并且使用 Status 赋值给了一个变量 myStatus。


  • OCTET STRING


8 进制表示的字符串:


octetExample ::= OCTET STRING
复制代码


  • DATE


表示日期,格式是"YYYY-MM-DD":


birthday DATE ::= "1990-11-18"
复制代码


  • TIME-OF-DAY


表示日期中的时间,格式是"HH:MM:SS":


startTime TIME-OF-DAY ::= "09:30:00"
复制代码


  • DATE-TIME


时间加日期的格式,它的格式"YYYY-MM-DDTHH:MM:SS",如下所示:


endTime DATE-TIME ::= "2022-01-10T18:30:23"
复制代码


  • REAL


REAL 表示的是一个浮点数,可以如下表示:


Amount ::= REAL
复制代码


  • ENUMERATED


ENUMERATED 表示的是一个枚举,可以如下表示:


Colors ::= ENUMERATED {black, red, white}myColor Colors ::= white
复制代码


  • SEQUENCE


SEQUENCE 表示的是项目的序列合集,如下所示:


StudentInfo ::= SEQUENCE {name VisibleString,phone NumericString}max StudentInfo ::= {name "J.Max", phone "18888888888"}
复制代码


  • SEQUENCE OF


SEQUENCE OF 表示的是一个 list:


breakTimes SEQUENCE OF TIME-OF-DAY ::= {"10:00:00", "12:00:00", "14:45:00"}
复制代码


  • CHOICE


CHOICE 表示从众多的 item 中选择一个:


Identity ::= CHOICE {name VisibleString,phone VisibleString,idCard VisibleString}jack Identity ::= name: "jack"
复制代码


  • IA5String


IA5String 表示的是 ASCII 字符,并且包含有控制字符。


SampleString ::= IA5String
复制代码


  • VisibleString


VisibleString 表示的是 ASCII 字符,其中不包含有控制字符。


SampleString ::= VisibleString
复制代码


  • NumericString


NumericString 表示的是数字和空格。


SomeNumber ::= NumericString
复制代码


  • UTF8String


UTF8String 表示的是 Unicode 字符


UnicodeString ::= UTF8String
复制代码


  • NULL


是一个空值,用来占位。

ASN.1 中的限制语法

ASN.1 中可以定义很多个字段,有些字段可能会有一些限制,比如手机号只能用数字,名字有长度限制等。


这些限制在 ASN.1 中叫做 Constraints,一般来说有下面的一些限制:


  • FROM


FROM 提供了一个数据值的读取范围,如下:


PermittedChars ::= IA5String (FROM("ABCDEFG1244"))
复制代码


PermittedChars 只允许从"ABCDEFG1244"选择。


  • PATTERN


PATTERN 表示的是正则表达式,如下所示:


phoneNumber ::= IA5String (PATTERN "1[0-9]#10")
复制代码


上面列出的是一个简单的手机号码的正则表达式。


  • SIZE


SIZE 可以表示字符串的长度或者数组的长度:


       Name ::= IA5String (SIZE (4..7))       NameList ::= SEQUENCE SIZE (1..25) OF Name
复制代码


  • RANGE


使用..可以表示一个范围:


Age ::= INTEGER (0..100)
复制代码


  • 单一值


从提供的值列表中挑选一个:


Colors ::= UTF8String ("Blue" | "White")
复制代码

总结

以上就是 ASN.1 数据结构描述语言的基本介绍了,有了这些基础,我们就可以很容易读懂使用 ASN.1 来描写的数据结构了。


更多内容请参考 http://www.flydean.com/46-asn-1/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2022 年 05 月 27 日阅读数: 21
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
密码学系列之:ASN.1接口描述语言详解_密码学_程序那些事_InfoQ写作社区