ASN.1编码规则详解(最全最经典)(1)
更新时间:2023-09-14 07:25:01 阅读量: 初中教育 文档下载
- asn.1基本编码规则推荐度:
- 相关推荐
ASN.1编码规则详解
1 简介
? 注释:
本章的内容主要翻译自《ASN.1 Communication between Heterogeneous Systems》和《ASN.1 Complete》。
1.1 ASN.1简介
ASN.1 (Abstract Syntax Notation dot one),抽象记法1。数字1被ISO加在ASN的后边,是为了保持ASN的开放性,可以让以后功能更加强大的ASN被命名为ASN.2等,但至今也没有出现。
ASN.1是定义抽象数据类型规格形式的标准。是用于描述数据的表示、编码、传输、解码的灵活的记法。它提供了一套正式、无歧义和精确的规则,以描述独立于特定计算机硬件的对象结构。
ASN.1是通信协议中描述数据传输的正式标记(notation),它与语言实现和物理表示无关,与应用的复杂度无关。ASN.1特别适合表示现代通信应用中那些复杂的、变化的及可扩展的数据结构。
ASN.1发送任何形式(音频、视频、数据等等)的信息都必须用数字传送。ASN.1只能包含信息的结构方面(没有已经定义的或考虑到的处理数据值的操作)。它不是一个编程语言。
ASN.1 本身只定义了表示信息的抽象句法,但是没有限定其编码的方法。各种ASN.1 编码规则提供了由ASN.1描述其抽象句法的数据的值的传送语法(具体表达)。标准的ASN.1 编码规则有基本编码规则(BER,Basic Encoding Rules)、规范编码规则(CER,Canonical Encoding Rules)、唯一编码规则(DER,Distinguished Encoding Rules)、压缩编码规则(PER,Packed Encoding Rules)和XML编码规则(XER,XML Encoding Rules)。
ASN.1成功的一个主要理由是它采用了一些如BER(Basic Encoding Rules)或新制定的PER(Packed Encoding Rules)这样的标准化的编码规则,它对受带宽限制的应用程序很有用。
这些编码规则描述了如何将定义在ASN.1中的值译成适合传输的电码(例如:他们可以被转化为可传输的字节,或反向转化),其与机器、编程语言或者在应用程序中的表示无关。ASN.1的编码方式比很多竞争者更先进,能够快速并可靠的传输可扩展信息--这是无线带宽的一个优势。由于从1982年以后ASN.1已经成为一个国际标准,所以它的编码规则是成熟的并且它有长期的可靠性和互用性的跟踪记录。一个的ASN.1源文件可以非常容易地(由预处理器)映射为C或C++或Java数据结构,可用于通过应用程序代码,和支持的运行时库提供的编码和解码的申述或者一个XML或限值的格式,或非常紧凑的压缩编码格式。
几乎所有操作系统上的工具都支持ASN.1,ASN.1支持如java,c和c++这样流行的编程语言,和包括COBOL这样的较老的编程语言。ASN.1的广泛性的一个例子是,有很多工具已经支持超过150种不同的计算机平台。有大量经过检验的ASN.1工具已经被长期使用。
ASN.1是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序 — 不论是非常复杂的,还是非常简单的。
在任何需要以数字方式发送信息的地方,ASN.1 都可以发送各种形式的信息(声频、视频、数据等等)。ASN.1 和特定的 ASN.1 编码规则推进了结构化数据的传输,尤其是网络中应用程序之间的结构化数据传输,它以一种独立于计算机架构和语言的方式来描述数据结构。
ISO 协议套中的应用层协议使用了 ASN.1 来描述它们所传输的 PDU,这些协议包括:用于传输电子邮件的 X.400、用于目录服务的 X.500、用于 VoIP 的 H.323 和 SNMP。它的应用还可以扩展到通用移动通信系统(UMTS)中的接入和非接入层。
简洁的二进制编码规则(BER、CER、DER、PER,但不包括 XER)可当作更现代 XML 的替代。然而,ASN.1 支持对数据的语义进行描述,所以它是比 XML 更为高级的语言。 ASN.1 的描述可以容易地映被射成 C 或 C++ 或 Java 的数据结构,并可以被应用程序代码使用,并得到运行时程序库的支持,进而能够对编码和解码 XML 或 TLV 格式的,或一种非常紧凑的压缩编码格式的描述。
同时,ASN.1是一种用于描述结构化客体的结构和内容的语言。 抽象语法定义:
ASN.1是描述在网络上传输信息格式的标准方法。它有两部分:一部分描述信息内数据,数据类型及序列格式;另一部分描述如何将各部分组成消息。它原来是作为X.409的一部分
而开发的,后来才自己独立成为一个标准。ASN.1在OSI的ISO 8824/ITU X.208(说明语法)和ISO 8825/ITU X.209(说明基本编码规则)规范。
例如:
Report ::= SEQUENCE {
author OCTET STRING, title OCTET STRING, body OCTET STRING, biblio Bibliography }
在这个例子中,\是由名字类型的信息组成的,而SEQUENCE表示消息是许多数据单元构成的,前三个数据单元的类型是OCTET STRING,而最后一个数据类型则下面的ASN.1语法表示它的意义:
Bibliography ::= SEQUENCE {
author OCTET STRING title OCTET STRING publisher OCTET STRING year OCTET STRING }
ASN.1 提供了一些基本的预定义数据类型: UNIVERSAL 0 保留给编码规则使用 UNIVERSAL 1 布尔类型 UNIVERSAL 2 整型
UNIVERSAL 3 二进制字符串类型 UNIVERSAL 4 八进制字符串类型 UNIVERSAL 5 空类型 UNIVERSAL 6 对象标识符类型
UNIVERSAL 7 对象描述符类型 UNIVERSAL 8 外部类型和类型实例 UNIVERSAL 9 实数类型 UNIVERSAL 10 枚举类型 UNIVERSAL 11 嵌入的 pdv 类型 UNIVERSAL 12 UTF8 字符串类型 UNIVERSAL 13 相关对象标识符 类型
UNIVERSAL 14-15 保留给本建议的以后版本和国际标准使用 UNIVERSAL 16 序列和类型序列 UNIVERSAL 17 集合和类型的集合 UNIVERSAL 18-22, 25-30 字符串 类型 UNIVERSAL 23-24 时间 类型
UNIVERSAL 31-... 保留给本建议以外的类型和国际标准使用 ASN.1 还能够定义如下的数据结构类型: 结构 ( SEQUENCE ), 列表 ( SEQUENCE OF ), 类型选择 ( CHOICE ), 等等
不同体系的系统,不同编程语言之间,都存在通讯障碍。如Figure 1-1 a)所示极端情况下,为了保证网络中n个异体的节点能互通,我们需要为每个节点编写(n-1)个编解码程序,即需要总数为n*(n-1)个编解码程序。在b)所示极端情况下,为了保证互通,需要为每个节点编写1个编码和1个解码程序,即总数为2n个编解码程序。
Figure 1-1 两种类型的通讯方式
对于给定的记法描述,ASN.1编译器能执行并产生如Figure 1-2图中虚线部分,这样我们以有限的代价就能完成相当多数量系统之间的互连。
Figure 1-2 语法三元组:实际语法、抽象语法和传输语法
(1)实际语法(Concrete Syntax)
指诸如C、Objective Caml等这样实际编程语言; (2)抽象语法(Abstract Syntax)
指ASN.1,是协议采用ASN.1规范描述的描述文本。描绘了与任何表示数据的编码技术无关的通用数据结构。抽象语法使得人们能够定义数据类型,并指明这些类型的值。抽象语法只描述数据的结构形式,与具体的编码格式无关,同时也不涉及这些数据结构在计算机内如何存放。 (3)传输语法(Transfer Syntax)
指表示层交换数据的表示方法,是实际通讯系统间的码流。当数据在两个表示层实体之间传输时,这些数据的实际比特模式表示方法就是传送语法。 (4)编码
指用来表示数据值的完整的八位组序列。 (5)编码规则
从一个语法到另一个语法的映射规约。具体地说,编码规则从算法上定义了任何一组由抽象语法定义的数据值在传送语法中的表示。
下图以两个端系统通过网络交换数据为例来说明上述的一些概念。
开始于1982年夏天,许多开发应用层标准的人意识到他们面临同一个问题:数据结构变得越来越复杂,难以用预定的规程来编解码bit或者Byte(在1978年,OSI中术语Open是至关重要的)。如同编译器取代了汇编器,通常认为编码器应当从描述Specification自动产生,这样使得描述也等效为一种计算机程序。
1.4.1 诞生
James White和Douglas Steedman分别提出一个基本的记法和算法,这套记法能定义Email消息控制系统协议MHS(Message Handling System)的编码比特格式。这种记法和编码规则是与机器无关的,能表述复杂的数据结构。
James White当时是CCITT X.400 (MHS)建议系列的起草人,并且为施乐公司(Xerox Corporation)设计了Courier记法,这种记法能翻译XNS(Xerox Network Services)的RPC(Remote Procedure Call)传送的数据。Courier作为第一种外部的数据记法而闻名。同时它对后来的XDR(来自Sun Microsystems Inc.)和NDR(来自Apollo Computer Inc.)都产生了积极的影响。
1984年,CCITT将这种记法标准化,参考号为X.409(红皮书)。X.409建议成为:Message Handing Systems: Presentation Transfer Syntax And Notation。它的目标和范围为:“the
presentation transfer syntax used by application layer protocols in message handling systems and by the document interchange protocol for the telematic services. In the architecture of open systems interconnection (OSI), a presentation transfer syntax is used to represent information exchanged between application entities”
X.409记法和MHS系统是完全独立的,部分原因是Email协议处理的对象是十分复杂的,没有大小限制,多种字符串类型,链接的结构,为数众多的选项等。结果,许多OSI应用标准化工作组发现这种记法对他们也有用。
1.4.2 1989和1990版本
如前所述,1987年ISO和IEC成立了JTC 1。
1989年CCITT发布了两个文档X.208(ASN.1)和 X.209(BER)来替代X.409建议。其中很多新特性是由JTC 1引入的:subtypes, floats (REAL type), pointers (ANY DEFINED BY type)
and the default tagging modes (IMPLICIT TAGS and EXPLICIT TAGS)。他们这套X.200系列称为“General OSI Infrastructure”,表示ASN.1成为应用层一种独立的描述语言。
1990年ISO发布了新的ISO 8824和ISO8825标准,和X.208相比,有三处地方相悖。具体问题请参考1.6.1 CCITT 1989版本和ISO 1990版本的冲突。
自1998年开始,ISO和ITU-T联合发布他们的标准文本,避免再次出现标准间的冲突。
1.4.3 1994版本
新的版本(实际是1994年完成草案) ASN.1 :1994于1995年被ISO通过,成为正式标准。为了阐述数目众多的条件和介绍新概念,该标准分为四个部分:
1) ITU-T Rec. X.680 (1994) | ISO/IEC 8824-1:199518: Specification of Basic Notation,
2) ITU-T Rec. X.681 (1994) | ISO/IEC 8824-2:1995: Information Object Specification,
3) ITU-T Rec. X.682 (1994) | ISO/IEC 8824-3:1995: Constraint Specification,
4) ITU-T Rec. X.683 (1994) | ISO/IEC 8824-4:1995: Parameterization of ASN.1 Specifications,
几个月之后,发布了两个补充和一个技术勘误表:
? ITU-T Rec. X.680/Amd.1 (1995) | ISO/IEC 8824-1:1995/Amd.1: Rules of
Extensibility,
? ITU-T Rec. X.680/Corr.1 (1995) | ISO/IEC 8824-1:1995/Corr.1: Technical
Corrigendum 1,
? ITU-T Rec. X.681/Amd.1 (1995) | ISO/IEC 8824-2:1995/Amd.1: Rules of
Extensibility.
编码规则部分被分成了两个部分(和一个技术勘误表):
? ITU-T Rec. X.690 (1994) | ISO/IEC 8825-1:1995: ASN.1 Encoding Rules:
Specification of Basic Encoding Rules, Canonical Encoding Rules, and Distinguished Encoding Rules,
? ITU-T Rec. X.690/Corr.1 (1995) | ISO/IEC 8825-1:1995: Technical
Corrigendum 1,
? ITU-T Rec. X.691 (1995) | ISO/IEC 8825-2:1995: ASN.1 Encoding Rules:
Specification of Packed Encoding Rules
这些标准给出了官方正式编码规则,这对诸如传输加密数据情况来说是必需的。 1994版本和以前版本相比的差异和新特性,请参考1.6.2 错误!未找到引用源。。
1.4.4 1997版本
语义模型分为三个补充文件:
? ITU-T Rec. X.680 (1997)/Amd.2 (1999) | ISO/IEC 8824-1:1998/Amd.2 ? ITU-T Rec. X.681 (1997)/Amd.1 (1999) | ISO/IEC 8824-2:1998/Amd.1 ? ITU-T Rec. X.683 (1997)/Amd.1 (1999) | ISO/IEC 8824-4:1998/Amd.1
相关对象标识符新的RELATIVE-OID类型说明在三个补充文件:
? ITU-T Rec. X.680 (1997)/Amd.1 (1999) | ISO/IEC 8824-1:1998/Amd.1 ? ITU-T Rec. X.690 (1997)/Amd.1 (1999) | ISO/IEC 8825-
1:1998/Amd.1
? ITU-T Rec. X.691 (1997)/Amd.1 (1999) | ISO/IEC 8825-2:1998/Amd.1
新增四个技术勘误表:
? ITU-T Rec. X.680 (1997)/Corr.1 (1999) | ISO/IEC 8824-1:1998/Corr.1 ? ITU-T Rec. X.681 (1997)/Corr.1 (1999) | ISO/IEC 8824-2:1998/Corr.1 ? { ITU-T Rec. X.690 (1997)/Corr.1 (1999) | ISO/IEC 8825-1:1998/Corr.1 ? { ITU-T Rec. X.691 (1997)/Corr.1 (1999) | ISO/IEC 8825-2:1998/Corr.1
1994版本和以前版本相比的差异和新特性,请参考1.6.3 1997版本新特性和1.6.4 错误!未找到引用源。。
1.4.5 最新版本
目前最新版本的协议为:
? ITU-T X.680 (ISO/IEC 8824-1) - Abstract Syntax Notation One (ASN.1):
Specification of Basic Notation
? ITU-T X.681 (ISO/IEC 8824-2) - Abstract Syntax Notation One (ASN.1):
Information Object Specification
? ITU-T X.682 (ISO/IEC 8824-3) - Abstract Syntax Notation One (ASN.1):
Constraint Specification
? ITU-T X.683 (ISO/IEC 8824-4) - Abstract Syntax Notation One (ASN.1):
Parameterization of ASN.1 Specifications
? ITU-T X.690 (ISO/IEC 8825-1) - ASN.1 Encoding Rules: Specification of
Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
? ITU-T X.691 (ISO/IEC 8825-2) - ASN.1 Encoding Rules: Specification of
Packed Encoding Rules (PER)
? ITU-T X.692 (ISO/IEC 8825-3) - ASN.1 Encoding Rules: Specification of
Encoding Control Notation (ECN)
? ITU-T X.693 (ISO/IEC 8825-4) - ASN.1 Encoding Rules: Specification of
XML Encoding Rules (XER).
? ITU-T X.694 (ISO/IEC 8825-5) - ASN.1 Encoding Rules: Mapping W3C
XML schema definitions into ASN.1.
1.5 ASN.1应用情况
? Accredited Standards Committee X9 - Financial Services ? Manufacturing Message Specification (MMS) ? Molecular Biology Standards ? Request For Comments (RFC)
? RSA Public-Key Cryptography Standards
? Standard Security Label for Information Transfer ? Secure Electronic Transaction (SET) ASN.1 ? T.120 Series Standards
? Telecommunications Management Network (TMN) ? Unicode Worldwide Character Standard
? X.400 Standards - Message Handling Systems ? X.500 Standards - The Directory ? H.323 ? H.248 ? 3G on UMTS
等等。
现在一些协议,标准组织在给出协议文本时往往也同时给出了ASN.1的描述。
2 基础知识
? 注释:
本章的内容主要翻译自《ASN.1 Communication between Heterogeneous Systems》。
2.1 相关背景知识
2.1.1 OSI参考模型
7th layerApplication7th layer protocolApplicationAPDVPPDVSPDVTPDVPacketsFrameBitInterface between the 6th and 7th layers6th layer5th layer4th layer3rd layer2nd layer1st layerPresentation6th layer protocolPresentationSessionSessionTransportTransportNetworkNetworkData linkData linkPhysicalPhysicalPhysicalFigure 2-1 OSI 七层参考模型
1)表示层 Presentation Layer
两个系统在传输数据前需要协商共用的编码方式。表示层负责在两个应用系统间进行编码方式协商和实际信息的编码。
为了达到这个目的,表示层需使用以下概念:
(1)抽象语法:定义了数据的常用结构(包括不同的数据类型),并且建立了和应用层对话所依赖的框架。
(2)实际语法:本地的,并且定义本地系统的数据表示方法。 (3)传输语法:定义两个系统间的表示层间交换数据的表示方法。
(4)编码规则:提供从本地实际语法到传输语法和其相反操作的方法。(第1章中说过:
从抽象语法到传输语法,由ASN.1编译器按照编解码规则实现。)
应用这些记法,表示层能够提供应用层这些服务:
(1)传输语法的协商(在会话开始前挑选一种传输语法的方法,改变传输语法的方法); (2)确定传输语法的集合(抽象语法的多种表示方式);
(3)用实际语法(内部表示方式)的编码/解码规则来翻译为传输语法(外部表示方式)或者做相反操作;
(4)把一个协商后的传输语法和应用内部采用的抽象语法进行关联; (5)访问会话层服务。
Application AApplication B1 P-CONNECT.request (AS1,AS2)6.P-CONNECT.conˉrm (AS2)3. P-CONNECT.indication (AS1,AS2)4. P-CONNECT .response (AS2)2. PPDV = AS1(TS1),AS2(TS2,TS3)Presentation A5. PPDV = AS2(TS2)Presentation B Figure 2-2 表示层上下文协商 在 Figure 2-2 表示层上下文协商表示层上下文协商中,详细描述了这样一个过程:
(1)应用A发送一个P-CONNECT.request原语给自己的表示层,并且声明操作这个传输的相关抽象语法名字为(AS1,AS2)。每个抽象语法的名字实际是一串成为对象标识符(Object Identifier,在ASN.1中是OBJECT IDENTIFIER类型的值)的数字,它能唯一的标识抽象语法。的确,我们应当注意到这是一个开放式的架构,能适应各种机器,各种抽象语法,各种传输语法。
(2)表示层为每个抽象语法关联传输语法,并且为会话层编码“表示(层)协议数据值”PPDV(Presentation Protocol Data Value),这些数据会被送往对方系统的表示层。PPDV中包含着可用的抽象语法。
(3)表示层B收到这个PPDV数据后,向自己的应用层回送P-CONNECT.indication原语,指示应用A的抽象语法可用。
(4)应用B以P-CONNECT.response原语应答,指示在这个传输中可用的抽象语法的名字(这里只指示AS2)。
(5)会话层B接收到原语后,发送PPDV指明传输语法,这个语法应当是已经协商中的一个(如上图中是T2、T3中的T2)。
(6)最后,表示层A收到PPDV后,检查对方推荐的传输语法,如果接受它则发送P-CONNECT.confirm原语给应用A。
应当注意,表示层没有参与到应用间可用抽象语法的确定过程中。通常,会用多个抽象语法/传输语法的组合关系。一个抽象语法可以用多个传输语法来表示;一个传输语法也可以用来表示多个抽象语法。抽象语法/传输语法组合的协商结果被称为“表示上下文”(Presentation Context)。上下文用整数来标识,为了防止重新分配时出现覆盖,一般让一个实体采用偶数而另一个实体采用奇数。其它上下文可以在通讯过程中动态协商。
在初始协商的最后,系统在它的配置中有了一套“表示上下文”,在任何时候,系统都能从中选出合适的上下文进行交换操作。
来自应用层的数据会被根据相关的“表示上下文”进行编码。当只有一个上下文被指定时,他们将被直接编码(简单编码 Simple Encoding);否则应用数据包括嵌入数据(embedded data)都要在前面加上正确的上下文标识符(完整编码 Complete Encoding)。 2)应用层 Application Layer
采用OSI模型时,我们称一个应用的一个通讯方面为一个应用实体。通讯实体用通讯
协议和表示业务来共享信息。
在ASN.1中,各个应用的数据结构作为“应用(层)协议数据值”APDV(Application Protocol Data Value)发送。每当要传输数据时,应用实体都会在给出APDV的同时,告知表示层自己的ASN.1名字。通过参考ASN.1的定义,表示层可以得知数据单元的类型和长度,以及传输时应当采用的编码方法。在连接的另一端,表示层分析收到数据结构中的ASN.1标识符,就能得知第一个数据单元有多少比特,第二个有多少,等等。有了这些信息,表示层按照接收方内部格式对数据做必要的转换。
自从ISO要求所有的应用层和表示层数据交换都要用ASN.1抽象语法描述后,ASN.1在OSI中只作为表示方法用。随着OSI模型的广泛应用,ASN.1主要用在高层中(部分因为在ASN.1出现前,许多低层已经存在了),但这不是一种限制。如果ASN.1能广泛应用在低层中,就能充分影响编码过程,阻止数据在不同层上反复出现。 2.1.2 边界对齐
对于同样一条消息,在计算机内存中是以Byte为单位存储的,在链路上则是以bit为单位传送的。对于其中每个信元IE,当从bit流映射到Byte流时,就涉及到边界对齐的问题:
如果一个信元的第一个bit也恰好是Byte流中某Byte的开始bit时,我们称之为开始于边界对齐的;
如果信元的最后一个bit也恰好是Byte流中某Byte的最后一个bit时,则可以称之为结束于边界对齐的。
对于不是结束于边界对齐的情况,一般要进行补位。有两种方式:
(1)对每个信元的结束立即进行补位,保证下一个信元是开始于边界对齐的;
(2)从信元结束的位置开始新的信元,到消息结束时再进行一次补位操作。(用于无线空口中)
通常第一种方式用在对消息大小要求不苛刻的编码过程中和通常的解码过程中;第二种方式用在对消息大小要求苛刻的编码过程中(如无线通讯系统的空中接口消息编码中)。
当把边界对齐问题和大小端问题放在一起时,常常会造成理解上的困难。某些协议中为了明确表示位域跨字节情况下的排列,用MSB、LSB标识最高、最低bit的位置所在。
2.1.3 大小端(Big Endian vs Little Endian)
? <1>大端方式(MSDN中说的网络序):Motorola的PPC系列、IP协议中;(该方式和书写方式一致)
? <2>小端方式(MSDN中说的主机序):VAX计算机、Intel的x86系列;
字节内部的bit高低次序相同(左高右低),而字节之间的高低次序相反。 在32位系统中我们分以下这些情况来一一说明: 1)Byte类型(8bits)
在只有一个Byte的情况下,大端方式和小端方式没有分别。如:0x34
Big Endian Little Endian bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 0 0x34 0x34 2)Short类型(16bits)
大小端方式之间有差别。如:0x1234
Big Endian (0) Big Endian (1) Little Endian (0) Little Endian (1) 0 0 0 1 0 0 1 0 0x12 0 0 1 1 0 1 0 0 0x34 0 0 1 1 0 1 0 0 0x34 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 0 0 0 1 0 0 1 0 0x12 3)Long类型(32bits)
大小端方式之间有差别。如:0x12345678 Big Endian (0) Big Endian (1) Big Endian 0 1 0 1 0 1 1 0 0x56 0 0 1 1 0 1 0 0 0x34 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 0 0 0 1 0 0 1 0 0x12 (2) Big Endian (3) Little Endian (0) Little Endian (1) Little Endian (2) Little Endian (3) 0 0 0 1 0 0 1 0 0x12 0 0 1 1 0 1 0 0 0x34 0 1 0 1 0 1 1 0 0x56 0 1 1 1 1 0 0 0 0x78 0 1 1 1 1 0 0 0 0x78 4)位域的情况(边界对齐问题+大小端问题):
大小端方式之间有明显的差别。
在一个字节内,如3-4-1结构下的{4, 15, 0} Big Endian Little Endian 跨字节,边界不对齐,如5-4-7结构下的{2, 15, 0} Big Endian (0) Big Endian (1) Little Endian (0) Little Endian (1) 1 1 1 0 0 0 1 0 0xE2 0 0 0 0 0 0 0 1 0x01 1 0 0 0 0 0 0 0 0x80 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 0 0 0 1 0 1 1 1 0x17 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 1 0 0 1 0 1 1 1 1 1 1 1 1 0 0 0 0x9E 0x7C 2.2 基本语法规则
到目前为止,ASN.1记法仍然主要是BNF(Backus-Naur Form)形式的。
1)在ASN.1中,符号的定义没有先后次序:只要能够找到该符号的定义即可,而不必关
T ::= [1] IMPLICIT T1 T1 ::= [5] IMPLICIT T2
T2 ::= [APPLICATION 0] IMPLICIT INTEGER 对于类型T,只有Tag值 1被编码。
这种模式需要接收方能保证清楚知道抽象语法,能正确解码。 III. Global Tagging Mode
可以在模块定义时,声明模块全局Tag模式。可以是EXPLICIT TAGS、IMPLICIT TAGS和AUTOMATIC TAGS。
IMPLICIT TAGS:模块内所有SEQUENCE、SET和CHOICE的成员都是IMPLICIT模式(除非它是CHOICE类型、开放类型或者一个参数类型)。但不影响IMPORTS的内容。
AUTOMATIC TAGS:模块内所有SEQUENCE、SET和CHOICE类型ASN.1编译器会自动从0开始,步长为1进行自动编码。而其中的成员则用IMPLICIT模式,除非它是CHOICE类型、开放类型或者一个参数类型。
下面两个定义是等效的:
M DEFINITIONS AUTOMATIC TAGS ::= BEGIN
T ::= SEQUENCE {
a INTEGER, b CHOICE {
i INTEGER, n NULL },
c REAL } END
M DEFINITIONS ::= BEGIN
T ::= SEQUENCE {
a [0] IMPLICIT INTEGER, b [1] EXPLICIT CHOICE {
i [0] IMPLICIT INTEGER, n [1] IMPLICIT NULL },
c [2] IMPLICIT REAL } END
如果使用全局AUTOMATIC TAGS模式时,在描述中给一个类型指定了一个Tag,那么对这个类似的AUTOMATIC TAGS就关闭。如果一个SEQUENCE或者SET类型包含COMPONENTS OF条目,而且这个条目在自动编号前展开;但自动标号又要求在展开前进行,ASN.1编译器要自己检查这种冲突。
对新的协议现在都推荐使用AUTOMATIC TAGS。 2.10.2 SEQUENCE
SEQUENCE是最常用的ASN.1类型之一,它可以嵌套使用,还可以使用OPTIONAL、DEFAULT和COMPONENTS OF等对成员进行修饰。
一个常见的SEQUENCE声明如:
Description ::= SEQUENCE {
surname IA5String, first-name age
}
该类型的一个值为:
johnny Description ::= {
surname first-name
\
\IA5String,
INTEGER
age
}
40
使用OPTIONAL和DEFAULT时,SEQUENCE类型应该能被明确解码,不存在模棱两可的地方。如下这个类型就有问题:
T ::= SEQUENCE {
x y z t
}
在使用BER编码规则时,对于值t1 T::={x 1, y 2, t 3}而言,接收方收到的码流如下: T2L1V1T2L1V2T2L1V3
INTEGER,
INTEGER OPTIONAL, INTEGER DEFAULT 0, INTEGER
Figure 2-6 OPTIONAL引起的歧义 那么在解码过程中,V为2的值无法确定是成员y还是成员z。这种情况下,该类型的定义应该在Tag上做一些补充: T ::= SEQUENCE {
x y z t
}
注意:对于接收方,没有收到声明DEFAULT的成员和收到DEFAULT的值是等价的。
在类型定义中,可以使用COMPONENTS OF将另一个类型的成员插入到当前类型中:
Registration ::= SEQUENCE {
COMPONENTS OF Description, marital-status ENUMERATED
{single, married, divorced,widowed}
INTEGER, -- [UNIVERSAL 2] [0] INTEGER OPTIONAL, [1] INTEGER DEFAULT 0, INTEGER -- [UNIVERSAL 2]
}
COMPONENTS的效果使得上面的定义等效于:
Registration ::= SEQUENCE {
surname first-name age
IA5String,
IA5String,
INTEGER,
marital-status ENUMERATED
{single, married, divorced, widowed}
}
而不是:
Registration ::= SEQUENCE {
description
Description,
marital-status ENUMERATED
{single, married, divorced,widowed}
}
使用COMPONENTS OF的好处在于,如上例中,Description更新升级时,Registration的内容不需要手工修改。
2.10.3 SET
和SEQUENCE相比,SET的成员是没有顺序的。同样可以使用OPTIONAL、DEFAULT和COMPONENTS OF。
2.10.4 SEQUENCE OF
SEQUENCE OF相当于某些语言中的动态数组或者列表:所有成员都是一个类型,数目不定。如:
PariTierce DEFINITIONS ::= BEGIN
SteepleChase ::= SEQUENCE OF INTEGER
END
相应的典型值为:
winningCombination SteepleChase ::= {5, 2, 12} no-one-arrived SteepleChase ::= { }
ASN.1提供一种元标记来编写和描述项目的注释、文档,以“@”开头,后接模块名称、类型名字成员序号或者“*”(表示全部),如:
-- @PariTierce.SteepleChase.* must be distinct
-- @PariTierce.SteepleChase.0 = 5 (horse no. 5 always wins!)
如果是在模块内,则“@”和模块名都可以省略,如:
-- SteepleChase.* must be distinct
-- SteepleChase.0 = 5 (horse no. 5 always wins!)
2.10.5 SET OF
和SEQUENCE OF相比,SET OF的成员是顺序的,其它类似。
2.10.6 CHOICE
CHOICE类型表示一种选择,类似UNION。该提供两个信息:被选择的选项,相应的值。也就是说对于类型:
Afters ::= CHOICE {
cheese dessert
}
它的一个值而言:
mine Afters ::= dessert:\
(注意:表示方法先是选择的选项dessert,而后是“:”,最后是值 ) 没有必要先定义一个枚举类型来表征具体的选项。
和SEQUENCE、SET类型不同,CHOICE没有缺省的UNIVERSAL Tag值,因为它是一些类型的集合,其中被选择项目的Tag会被作为CHOICE相关Tag。在和SEQUENCE、SET一起使用时,要注意使用AUTOMATIC TAGS或者context-specific Tags。如下面,类型U的定义有问题(Tag 0 和 1都重复了两次):
T ::= CHOICE { a [0] INTEGER,b [1] NULL } U ::= SET {
x y z {
c [1] BIT STRING, d [2] OCTET STRING }
}
[0] REAL, T, CHOICE
[0] IA5String, [1] IA5String
心在使用它之前是否被定义过。如:
employeeNumber EmployeeNumber ::= 12345 EmployeeNumber ::= [APPLICATION 2] INTEGER
2)所有的标识符、参考、关键字都要以一个字母开头,后接字母(大、小写都可以)、数字或者连字符“-”(但不能以连字符“-”结尾,也不能连续出现两个连字符),不能出现下划线“_”。 合法的:
INTEGER v1515 No-final-dash MY-CLASS 不合法的:
Final-dashdouble-- dash under score 1515 3M
3)关键字一般都是全部大写的,除了一些字符串类型,如PrintableString,UTF8String,等,因为这些都是由原类型OCTET STRING衍生出来的。
4)在标识符中,只有类型和模块名字是以大写字母开头的,其它标识符都是以小写字母开头的。
5)字符串有三种形式:
? <1>用引号引用的字符串: “This is a string”
? <2>单引号引用的二进制串后加大写字母B: ?01101?B
? <3>单引号引用的十六进制串后加大写字母H: ?0123456789ABCDEF?H
6)带小数点的小数形式不能在ASN.1中直接使用,在ASN.1中实数实际定义为三个整数:尾数、基数和指数。
7)注释以两个连字符“--”开始,结束于行的结尾或者该行中另一个双连字符。 8)如同大多数计算机语言,ASN.1不对空格、制表符、换行符和注释做翻译。但是在定义符号(或者分配符号Assignment)“::=”中不能有分隔符,否则不能正确处理。
2.3 类型与类型定义
2.3.1 ASN.1中的类型
ASN.1中的一个重要概念就是类型。类型是一个非空的值的集合,可以被编码后传输。相比与高级语言中复杂的数据结构,ASN.1中的类型主要是为了数据的传输(比如为SEQUENCE和SET定义了OPTIONAL条目)。而BIT STRING和EMBEDDED PDV则是为了通讯专门设计的。
ASN.1中的基本类型如Table 2-1中所示,更为复杂的类型可以由基本类型通过如Table 2-2中的组合类型构造得到。
Table 2-1 内建数据类型 类型 NULL 含义 只包含一个值NULL,用于传送一个报告或者作为CHOICE类型中某些值 INTEGER REAL ENUMERATED BIT STRING OCTET STRING OBJECT IDENTIFIER, RELATIVE-OID EXTERNAL, EMBEDDED PDV …String(除了BIT STRING、各种字符串,有NumericString、OCTET STRING外) PrintableString、VisibleStirng、ISO64String、IA5String、TeletexStirng、T61String、VideotexString、GraphicString、GeneralString、UniversalString、BMPString和UTF8String CHARACTER STRING UTCTime, GeneralizedTime
允许为字符串协商一个明确的字符表 日期 全部整数(包括正数和负数) 实数,表示浮点数 标识符的枚举(实例状态机的状态) 比特串 字节串 一个实体的标识符,它在一个全世界范围树状结构中注册 表示层上下文交换类型 Table 2-2 组合类型 类型 CHOICE SEQUENCE SET SEQUENCE OF SET OF 含义 在类型中选择(相当于C中的联合) 由不同类型的值组成一个有序的结构(相当于C中的结构体) 由不同类型的值组成一个无序的结构 由相同类型的值组成一个有序的结构(相当于C中的数组) 由相同类型的值组成一个无序的结构 2.3.2 类型定义
<新类型的名字> ::= <类型描述> 其中:
<新类型的名字>是一个以大写字母开头的标识符; <类型描述>是基于内建类型或在其它地方定义的类型。
如:
Married ::= BOOLEAN Age ::= INTEGER Picture ::= BIT STRING Form ::= SEQUENCE {
name PrintableString, }
Payment-method ::= CHOICE {
check
Check-number,
SEQUENCE
age Age, married Married,
marriage-certificate Picture OPTIONAL
credit-card {
number Card-number,
}
expiry-date Date
}
注意:在SEQUENCE和SET等(好像应该是所有组合类型的)定义中,最后一个成员结尾没有逗号“,”。
为了接收方能正确解码,发送方为每个值的类型附加一个数,称为tag,在描述中以“[]”标识。缺省情况下,编码器会使用universal的tag。很多时候,缺省情况下不能消除所有的模糊性,有必要明确指出各成员的tag。
如:
Afters ::= CHOICE { }
cheese dessert
[0] PrintableString, [1] PrintableString
Coordinates ::= SET { x }
y z
[1] INTEGER, //这证明好像也可以用类来直接声明变量 [2] INTEGER,
[3] INTEGER OPTIONAL
注意:ASN.1允许递归式的类型分配(Assignment),但我们应当保证其中包含至少一个非递归的值,因为编码规则无法处理无限的值。当然,绝大多数结构类型的成员都终结于简单类型。
为了准确描述一个类型,我们需要对值的集合进行一定的限制。这用到子类型约束,在类型之后用圆括号进行标识。
如:
Lottery-number ::= INTERGER(1..49)
Lottery-draw ::= SEQUENCE SIZE(6) OF Lottery-number Upper-case-words ::= IA5String (FROM(“A”..”Z”))
Phone-number ::= NumericString (FROM(“0”..”9”))(SIZE(10))
Coordinates-in-plan ::= Coordinates (WITH COMPONENTS {…, z ABSENT})
有约束的类型当然还是类型,可以用在任何一个可以使用类型的地方。
最后,因为版本升级,在新的描述中,出现新的成员被加入到SEQUENCE、SET或者CHOICE或者在上述类型基础上添加约束而衍生的子类型时,两个连接的机器(特别是在开放网络中)不一定使用的是相同版本描述而生成的编解码器。为了防止一方因收到过多或者过少数据而出现错误,ASN.1中用符号“…”来标记可能以后是其它类型的地方。这样即使是旧的编解码器也不会因为描述扩充而导致编解码错误。
如:
以后新的版本中,描述可能为:
Type ::= SEQUENCE { }
component1 INTERGER, component2 BOOLEAN, …,
[[component3 REAL]], …
-- version 2
Type ::= SEQUENCE { }
component1 INTERGER,
component2 BOOLEAN, -- version 1 …
注意:新加入的类型成员要嵌套在“[[]]”中。
2.4 值定义
<新的值的名字> <该值的类型> ::= <值描述>
其中:
<新的值的名字>是以小写字母开头的标识符;
<该值的类型>可以是一个类型的名字,也可以是类型描述; <值描述>是基于整数、字符串、标识符的组合。 如:
counter Lottery-number ::= 45
sextuple Lottery-draw ::= { 7, 12, 23, 31, 33, 41 } pair Coordinates ::= { x 5, y -3 }
son-choice Afters ::= dessert:\date Date ::= \
在ASN.1的应用中,绝大多数的值都是动态获得的,但是指定某些值,特别是在约束型子类型中,提高描述的可读性。
如:
upper-bound INTEGER ::= 12 Interval ::= INTEGER (0..upper-bound) default-value Interval ::= 0 Pair ::= SEQUENCE {
first [0] Interval DEFAULT default-value, second [1] Interval DEFAULT default-value }
2.5 信息对象类和信息对象
<信息对象类> ::= CLASS <类描述> WITH SYNTAX <信息描述>
有时我们需要表达比注释更为正式的一些信息,例如我们要说明这样一个事实:一个结构类型的成员依赖于和这个结构类型相关的值。
如:
OPERATION ::= CLASS {
&number INTEGER UNIQUE, &Argument-type, &Return-result-type }
WITH SYNTAX {
OPERATION NUMBER &number
TAKES AN ARGUMENT OF TYPE &Argument-type AND RETURNS A VALUE OF TYPE &Return-result-type }
在ASN.1中我们没有指出操作的具体内容,但是我们给出了一个机器要求另一个机器执行这个操作所需要交换的数据结构。
域&number以小写字母开头,后面跟了类型INTEGER。这个整数值用作信息的标识符,因为后面加了UNIQUE关键字。
域&Argument-type和&Return-result-type以大写字母开头,后面什么都没有跟。他们是一些ASN.1类型的引用(这可能会因为类型没有定义而不能编码)。
WITH SYNTAX块定义了一个用户友好的语法,说明了这个类的成员。 上述信息对象类的一个对象定义如下:
plan-projection OPERATION ::= //为什么是小子字母开头 {
OPERATION NUMBER
12
TAKES AN ARGUMENT OF TYPE Coordinates AND RETURNS A VALUE OF TYPE Coordinates-in-plan }
因为两个通讯中的机器使用相同的描述,因此相同的信息对象就能在这两机器间共享。 一个给定类的所有对象,可以在描述中收集到一个对象集合中,如下:
SupportedOperations OPERATION ::= //为什么大写开头还要特别注明呢?一直不都是以大写开头的吗?
{
plan-projection | translation | symmetry, ... }
注意:和对象不同,对象集合以大写字母开头。字符“…”表明新的对象可以由通讯中的机器动态加入。
信息对象永远不会被编码,传递他们各项信息的唯一方法是在一个类型中引用他们。我们用上面这个信息对象集合来约束一个结构类型:
Execute-operation ::= SEQUENCE {
code OPERATION.&number({SupportedOperations}), argument OPERATION.&Argument-type ({SupportedOperations}{@code}) }
Receive-result ::= SEQUENCE {
code OPERATION.&number({SupportedOperations}), result OPERATION.&Return-result-type ({SupportedOperations}{@code}) }
这段晦涩的描述,声明了这样一种情况:
Execute-operation操作它的编号在code成员中,当其argument发送给对方时,一定要满足域&Argument-type的类型。链接(或者表约束)“@code”说明这个参数是依赖于操作的。
对方返回的Receive-result也有类似约束。
2.6 模块定义
<模块名字> DEFINITIONS <缺省Tag> ::= BEGIN
EXPORTS <导出描述> IMPORTS <导入描述> <模块体描述> END
一般协议由一个或者多个模块组成,模块用来收集数据结构定义。
模块名字必须以大写字母开头。模块能以一种“全局指针”(Universal Pointer)的方式来引用,称为对象标识符(Object Identifier),用花括号标识在名字之后。
如:
Module2 { iso member-body(2) f(250) type-org(1) ft(16) asn1-book(9) chapter5(0) module2(1) } DEFINITIONS AUTOMATIC TAGS ::= BEGIN
EXPORTS Type2;
IMPORTS Type1, value FROM Module1 {iso member-body(2) f(250) type-org(1) ft(16) asn1-book(9) chapter5(0) module1(0)}; Type2 ::= SEQUENCE OF Choice Choice ::= CHOICE {
a INTEGER (0..value), b Type1 } END
AUTOMATIC TAGS或者缺省,则说明不关注模块的tag交给编译器自己自动处理;如果需指明具体的tag值,则需要用“[]”来标识。此外tag的模式还可以是EXPLICIT TAGS和IMPLICIT TAGS。还可以使用EXTENSIBILITY IMPLIED来使模块中所有SEQUENCE、
SET、CHOICE和ENUMERATED类型可扩展。
条目IMPORTS和EXPORTS(不是必须的)定义模块的接口。其中IMPORTS声明在其它模块定义但在本模块会用到的类型或者值;EXPORT声明在本模块之外可以访问的类型或者值。
注意IMPORTS的语法为:
IMPORTS <名字>, value FROM < 其它模块的Object Identifier >; EXPORTS的语法为: EXPORTS <名字>;
使用IMPORTS时,没有类似IMPORTS ALL的语句能将一个模块中所有定义都导入,因此需要协议描述者逐条写出每个需要导入的符号。对于参数化的分配,需要使用花括号,如:
ModuleName DEFINITIONS ::= BEGIN
IMPORTS T{} FROM Module1; U ::= T{INTEGER} END
在BEGIN之后,IMPORTS之前的语句,则不使用导入的符号。
2.7 模块与分配(Assignment)
2.7.1 分配Assignment
有6种不同形式的数据与分配相关:类型、值、值的集合、信息对象类、信息对象和信息对象集合。 I. 定义一个新类型
如前所述,定义新类型,如:
TypeReference ::= CHOICE { }
integer INTEGER, boolean BOOLEAN
在协议最高层定义的类型中,不被其它类型引用的那种类型称为PDU(Protocol Data Unit),PDU是应用件交换的数据。 II. 定义一个值(绝对值)
如前所述,这种值不被编码,通常是用作DEFAULT,上下界或者信息对象中的。如:
value-reference TypeReference ::= integer:12
如果两个类型在语法上是完全一样的,则这两种类型的值可以相互赋值。如:
pair Pair ::= {x 5, y 13} couple Couple ::= pair
Couple ::= SEQUENCE { }
x y
INTEGER, INTEGER
Pair ::= SEQUENCE { }
x y
INTEGER, INTEGER
-------------------------------------------------------------------------------------------------------
Lighter-state ::= ENUMERATED {
on(0), off(1), out-of-order(2) }
Kettle-state ::= ENUMERATED {
on(0), off(1), out-of-order(2) }
lighter Lighter-state ::= on kettle Kettle-state ::= lighter
在最后一个例子中,这种类型和值之间的对应,是由称为“ASN.1语义模型”()来负责的。
III. 定义值集合
在语义上,一个值集合相当于一个添加约束后的类型。 如:
总结类型定义、值定义和值集合定义,我们可以得出这样的结论:
Table 2-3 分配语义定义
PrimeNumbers INTEGER ::= {2 | 3 | 5 | 7 | 11 | 13}
第一个词首字母 大写 小写 大写
第二个词首字母 / 大写 大写 ::= ::= ::= ::= 分配内容 类型或者信息对象类 值或者信息对象 值集合或者信息对象集合 2.7.2 本地和外部引用
除本地应用外,ASN.1还支持外部应用,但不推荐使用。如: MyType ::= SET OF OtherModule.Type 最好的方式依然是使用IMPORTS。
2.8 基本类型
Table 2-4 基本类型汇总表
类型 UNIVERSAL Tag 取值 BOOLEAN NULL INTEGER ENUMERATED REAL BIT STRING OCTET STRING OBJECT IDENTIFIER RELATIVE-OID
1 5 2 10 9 3 4 6 TRUE,FALSE NULL 整数 类型定义中列出的成员 实数 比特串 八位组串,字节流 13 2.8.1 BOOLEAN类型
是两个值的集合:TRUE,FALSE。如下:
RoundResult ::= BOOLEAN ok RoundResult ::= TRUE ko RoundResult ::= FALSE 该类型的UNIVERSAL Tag值为1。 2.8.2 NULL类型
空类型,只有一个值NULL。作为一种结果,空类型是传输报告和响应的典型情况。 Ack ::= NULL
它经常在时间信息中使用,表示传送时间没有赋值,如:
Clock ::= CHOICE { }
time UTCTime, out-of-order NULL
当时钟电池没有电时,值为:
battery-down Clock ::= out-of-order:NULL
NULL也可以用在表示链表结束的空接点,如:
LinkedList ::= SEQUENCE {
data Data,
}
当然,可以使用SEQUENCE OF来达到类似目的:
LinkedList ::= SEQUENCE OF Data next CHOICE { }
linked-list end NULL
LinkedList,
{ … }
该类型的UNIVERSAL Tag值为5。 2.8.3 INTEGER类型
整数可以是正整数也可以是负整数,取值范围在协议中没有界定。所以必须由编解码器提前确定好整数的范围,分配必要的内存空间来处理。可以通过在描述中增加一个值声明来判断:
Interval ::= INTEGER(123456789..123456790)
在使用PER编解码规则时,会按照本地整数范围进行截断;相比之下BER编码规则中因为有明确的长度,所以不会出现截断的情况。
虽然在数学可以有“-0”,但在ASN.1描述中不能这样描述。
一些情况下,比如为了定义错误码,需要给一些数值特定的名字,可以使协议更易于理解,也改善了应用层和编解码器之间的接口。这些信息当然可以用注释给出,但是ASN.1编译器不会使用这些信息,在词法分析开始,这些就都被忽略了。ASN.1为INTEGER类型提供了一种特殊语法来解决这个问题。以软盘驱动器的错误码为例:
ErrorCode ::= INTEGER {
disk-full(1), no-disk(-1), disk-not-formatted(2)
}
stupid-error ErrorCode ::= disk-full
这些名字只能被用于定义ErrorCode类型的值,不能用于其它类型值的定义。 命名的整数不需要排序。对于没有命名的整数,还是可以使用的;已经命名的整数,也可以直接使用数字:
ok ErrorCode ::= 0 stupid-error ErrorCode ::= 1
注意:这种命名使用的使花括号,不是约束(使用圆括号)。 这种方式和ENUMERATED类型相比,区别在于: <1>必须指定数值,不能像ENUMERATED中那样缺省;
<2>不能使用扩展标记“…”,当然这实际上不是个问题,和ENUMERATED不同,没有命名的整数还可以使用。
此外,这种方式如果使用不当,会造成混乱,要特别小心。如: alpha INTEGER ::= 1
Type1 ::= INTEGER { alpha(2) }
Type2 ::= INTEGER { alpha(3), beta(alpha) } gamma Type2 ::= beta delta Type2 ::= alpha
实际上gamma的值为1,delta的值为3。
注意:在ASN.1中,INTEGER和REAL类型之间没有兼容性,就是说不能将INTEGER的值赋给一个REAL类型的值。同样的,INTEGER和ENUMERATED类型间也不存在兼容性。
UNIVERSAL的Tag值为2。
2.8.4 ENUMERATED类型
ENUMERATED类型与INTEGER类型相比, 区别在于: <1>取值是受限制的,没有列出的数值不能使用; <2>数值是不能操作的,只能用于编码;
<3>不用明确指定数值,ASN.1可自动计算相应的数值(从0开始); <4>可以使用扩展,保证和新版本的编码兼容;
<5>是数值关联(显式或者隐式)到标识符,而INTEGER中则是标识符显式关联到数值。
ABRT-diagnostic ::= ENUMERATED {
no-reason-given(1), protocol-error(2),
authentication-mechanism-name-not-recognized(3), authentication-mechanism-name-required(4), authentication-failure(5), authentication-required(6), ... }
不能直接使用数字,如:
abert-diagnostic ABERT-diagnostic ::= 4 -- 错误的!
在使用扩展标记“...”时,需要注意的是,在扩展标记后的成员,其数值必须是升序排列的。
A ::= ENUMERATED {a, b, ..., c(0)} -- 错误: a 和 c 都是0
B ::= ENUMERATED {a, b, ..., c, d(2)} -- 错误: c 和 d 都是2
C ::= ENUMERATED {a, b(3), ..., c(1)} -- 正确: c = 1
和CHOICE、SEQUENCE和SET不同,在使用扩展标记“...”后,增加新成员时,ENUMERATED类型中不需要使用版本标识“[[ ]]”,并且只能有一个扩展标记。
注意事项:
<1>按照ASN.1的语义模型,任意两个ENUMERATED类型都是不兼容的。
<2>当一个ENUMERATED类型被IMPORTS到另一个模块中,则其列表中的标识符也被导入,但只能用于该类型值的赋值。
<3>基本列表(在扩展标识符之前)中的值不需要连续,也不需要排序。 <4>扩展列表(在扩展标识符之后)中的值不需要连续,但需要升序排列。
<5>扩展列表中的值不能和基本列表中的值重复,不论该值是明确指定的,还是缺省计算的。
扩展列表中成员的值必须比该列表中前一个成员的值大。(也就是所谓的升序吧) 表示成员值的必须是数字,不能是标识符。 该类型的UNIVERSAL Tag值为10。 2.8.5 REAL类型
从语义上等效于: SEQUENCE {
mantissa INTEGER (ALL EXCEPT 0), base INTEGER (2|10), exponent INTEGER }
但是REAL类型有自己特定的UNIVERSAL Tag值。 pi REAL ::= {314159, 10, -5}
e REAL ::= {271828128459045235360287, 10, -23} zero REAL ::= 0
注意:实数0不能用三元组的方式给出。
我们用PLUS-INFINITY和MINUS-INFINITY分别表示“正无穷大”和“负无穷大”,这两个也不能用三元组表示。
此外,我们也要注意到ASN.1中的实数只能以2或者10为底(base的约束)。
UNIVERSAL的Tag值为9。 2.8.6 BIT STRING类型
按照ASN.1的定义,BIT STRING长度可以为0。它可以是原始的bit流形式,也可以是布尔向量模型。 1)比特流形式:
pi-decimals BIT STRING ::=
'00100100001111110110101010001000100001 01101000110000100011010011000100110001 100110001010001011100000001101110000'B
pi-decimals BIT STRING ::= '243F6A8885A308D313198A2E0370'H 注意:这种形式下,要考虑大小端的影响。 2)布尔向量模型:
如Figure 2-4所示的权限示意图,当使用不同的比特表示权限时,在ASN.1中可以这样描述:
Rights ::= BIT STRING {
user-read(0), user-write(1), group-read(2), group-write(3), other-read(4), other-write(5) }
group1 Rights ::= { group-read, group-write } 当然,也可以之间用码字来赋值: group2 Rights ::= '0011'B group2 Rights ::= '3'H group3 Rights ::= '001100'B
weird-rights Rights ::= '0000001'B 注意:
命名的比特列表不影响值的声明;
命名的比特列表没有限制,位置也不必连续,也不对类型的长度产生影响。如weird-rights。
以码字赋值时,起始的比特是必须的(最左面的比特),用来定位。后续的0比特无意义。group2和group3 与group1的结果是一样的。
需要对BIT STRING长度进行约束时,可以使用SIZE,如:
RIGHTS ::= BIT STRING (SIZE(6))
和命名INTEGER类型相似,在命名BIT STRING中也不能使用扩展标记“…”。 和OCTET STRING类型一样,可以使用CONTAINING 和ENCODED BY来约束。 UNIVERSAL的Tag值为3。 2.8.7 OCTET STRING类型
与BIT STRING类型类似,但是单位不是比特而是8个比特的八位组。 UNIVERSAL的Tag值为4。 2.8.8 OBJECT IDENTIFIER类型
OBJECT IDENTIFIER类型是对象的唯一标识的集合,这里对象可以是(但不限于): <1>一种抽象语法,一定是在表示层无歧义的注册过(ISO8822);
<2>一种传输语法,一定是注册过,在表示层可以被抽象语法使用(ISO8823-1); <3>一种应用实体(ISO7498-3); <4>一个ASN.1模块;
<5>一种ROSE操作(ISO9072-2); 等等。
我们用注册树来表征所有注册的标识:
Figure 2-5 注册树
OBJECT IDENTIFIER类型就是该注册树所有叶子的路径集合。一个OBJECT
IDENTIFIER类型的值可以是:
internet-id OBJECT IDENTIFIER ::=
{ iso(1) identified-organization(3) dod(6) internet(1) }
francetelecom-id OBJECT IDENTIFIER ::= { iso member-body f(250) type-org(1) ft(16) }
ber-id OBJECT IDENTIFIER ::= { 2 1 1 }
即可以用各叶子的名字,可以用编号,也可以混合使用。 此外,对于多个有相同根名字的值,可以如下定义: ID ::= OBJECT IDENTIFIER
id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) } id-bp ID ::= { id-edims 11 }
id-bp-edifact-ISO646 ID ::= { id-bp 1 } id-bp-edifact-T61 ID ::= { id-bp 2 } id-bp-edifact-octet ID ::= { id-bp 3 } id-bp-ansiX12-ISO646 ID ::= { id-bp 4 } id-bp-ansiX12-T61 ID ::= { id-bp 5 } id-bp-ansiX12-ebcdic ID ::= { id-bp 6 }
每当一个对象注册到注册树中时,ISO标准ISO9834-1都会对它增加一个相应的文本描述,称之为ObjectDescriptor。如对上面ber-id的ObjectDescriptor为:
ber-descriptor ObjectDescriptor ::= \2.8.9 RELATIVE-OID类型
前面OBJECT IDENTIFIER类型可以看作是对象在注册树中的绝对路径,而RELATIVE-OID类型则是相对路径。其参考基准节点可以是一个OBJECT IDENTIFIER类型的值(动态的),或者是收发双方默认的(静态的)。
RELATIVE-OID可以使用CONSTRAINED BY进行约束。
2.9 字符串类型
Known-multiple Character String Type指字符串中每个字符编码所占字节数都一样。
Table 2-5 字符串类型一览表 类型名字 NumericString PrintableString Tag 字符表 18 19 字符“0”到“9”,空格 字符“A” 到 “Z”,“a”到“z”,“0”到“9”,空格,单引号(’),圆括号(( ,)),加号(+),逗号(,),减号(-),点(.),斜杠(/),冒号(:),等号(=),问号(?) VisibleString ISO646String IA5String 22 26 [ISOReg] entry no. 6; space [ISOReg] entry no. 1 & 6; space, delete TeletexString T61String 20 [ISOReg] entry no. 6, 87, 102, 103, 106, 107, 126, 144, 150, 153, 156, 164, 165, 168; space, delete VideotexString 21 [ISOReg] entry no. 1, 13, 72, 73, 87, 89, 102, 108, 126, 128, 129, 144, 150, 153, 164, 165, 168; space, delete GraphicString 25 all the graphical sets (called `G') of [ISOReg]; space GeneralString 27 all the graphical sets (called 是 是 是 是 是 是 ESC Multi 是 是 类型名字 Tag 字符表 `G') and all the control characters (called `C') of [ISOReg]; space, delete ESC Multi UniversalString BMPString 28 30 [ISO10646-1] the basic multilingual plane [ISO10646-1] (65,536 cells) 是 是 UTF8String
12 [ISO10646-1] 2.10 组合类型与扩展原则
2.10.1 Tag
传输数据时,一定要避免接收方收到数据解码时出现不清楚的地方。具体说,接收方要明确知道每个收到数据的类型,我们就要对各类型进行系统性的编号。在ASN.1的第一种编解码规则BER(Basic Encode Rule)中,对数据编码使用的是三元组规则:
分配给每个类型的tag实际上是一个值对:
UNIVERSAL的Tag是ASN.1标准定义的,在描述中不能修改。
Table 2-6 ASN.1中定义的UNIVERSAL类Tag Tag 0 1 类型 BER保留 BOOLEAN Tag 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 类型 INTEGER BIT STRING OCTET STRING NULL OBJECT IDENTIFIER ObjectDescripion EXTERNAL, INSTANCE OF REAL ENUMERATED EMBEDDED PDV UFT8String RELATIVE-OID 保留 保留 SEQUENCE, SEQUENCE OF SET, SET OF NumericString PrintableString TeletexString, T61String VideotexString IA5String UTCTime GeneralizedTime GraphicString VisibleString, ISO646String GeneralString UniversalString Tag 29 30 31 类型 CHARACTER STRING BMPString 保留
context-specific Tag是对SEQUENCE、SET和CHOICE及其成员使用的,可以在描述中自己定义,只要不产生歧义,相同数值可以在不同结构中反复使用。如:
A-possible-type ::= SET {
integer [0] CHOICE {
a [0] INTEGER, b [1] INTEGER },
boolean [1] CHOICE {
a [0] BOOLEAN, b [1] BOOLEAN } }
APPLICATION的Tag是为了“to define a data type that finds wide, scattered use within a particular application and that must be distinguishable (by means of its [ abstract syntax]) from all other data types used in the application”。在APPLICATION作用域内,其Tag也是唯一的。如:
Order-number ::= [APPLICATION 0] NumericString (SIZE (12))
但是因为使用IMPORTS等方式下,很难保证唯一性,所以这种Tag类(APPLICATION的Tag)已经不推荐使用了。
PRIVATE的Tag是为了“use a private-use Tagged [ type] to define a data type that finds use within a particular organization or country and that must be distinguishable (by means of its [ abstract syntax]) from all other data types used by that organization or country”。如一个公司可
能这样扩展传输层PDU:
RejectTPDU ::= SET { destRef yr-tu-nr credit extended }
PRIVATE类的Tag现在也不推荐使用了。 II. Tagging Mode
使用context-specific类Tag,如下: Afters ::= CHOICE {
cheese [0]IA5String, dessert [1]IA5String }
当没有其它更多描述信息,并且使用BER编码时,会将UNIVERSAL类和context-specific类的Tag同时编码出来。这种方式称为EXPLICIT模式。
在下面这种情况: T1 ::= [0] INTEGER 变更为:
T2 ::= [0] CHOICE {
integer INTEGER, real REAL }
当CHOICE取值为integer时不需要变更。
与之相对应的是IMPLICIT模式,它将只编码context-specific类的Tag,直到另一个UNIVERSAL类Tag出现。如:
[0] Reference, [1] TPDUnumber,
[2] Credit,
[PRIVATE 0] BOOLEAN DEFAULT FALSE
正在阅读:
山西省孝义市2017-2018学年高二物理下学期期末考试试题(扫描版)05-06
电气自动化专业论文112-19
与小苗同行作文600字07-03
哈尔滨工业大学干部任前公示11-13
时代光华《如何正确认知职责》课后试题答案12-01
画猪鼻子游戏作文350字06-26
【国家社会科学基金】_实践转化_基金支持热词逐年推荐_【万方软件创新助手】_2014080508-13
复三部曲式01-10
新土耳其的缔造者凯末尔05-17
- 二甲基甲酰胺安全技术说明书
- 南邮计算机网络复习题
- 高分子物理实验指导书 - 图文
- 2009.9.25 莞惠环控专业施工图设计技术要求
- 学生工作简报
- 揭阳市斯瑞尔环境科技有限公司废酸综合利用项目可行性研究报告-广州中撰咨询
- 今日靓汤(佘自强)
- 奥数 - 二年级 - 数学 - 第三讲时间的教师版计算答案 - 图文
- 如何命制一份好的物理试卷
- 数据库开题报告
- 禁用未经批准或已经废止或淘汰技术的制度流程
- 大学英语(二)第2阶段测试题
- 湘教版一年级上册美术教案(全)
- (整套)学生顶岗(毕业)实习手册
- 高频 二极管包络检波 - 图文
- 2018届中考英语复习题型四任务型完形填空备考精编含解析 - 186
- 郑煤集团超化煤矿一采区开采设计 - 图文
- 财政学习题
- 摄影摄像复习资料
- SMC D-A93接线方式 - 图文
- 详解
- 最全
- 编码
- 规则
- 经典
- ASN
- 钢筋安装作业指导书
- 药剂学模拟试题
- 箱涵预制施工方案 - 图文
- 中国营养保健品行业主要产品分类及市场分析
- 2016中考英语专项复习完型填空 社会历史类
- 线岔检修工艺
- 商城网站网络爬虫项目
- 采油工程实验-裂缝导流能力模拟实验
- 大同移动GSM网络替换前后对比报告(1115) - 图文
- 国外认知语言学研究的最新动态
- 地下矿山从业人员安全培训复习题-原题与参考答案
- 三年级下册数学每天一练
- 第二单元测试 答案
- 2014-2015学年育英学校七年级(普、实)历史与社会期中考试试卷
- 无机布双轨双帘特级防火卷帘门的构造及使用
- 海南省海口市2016年初中毕业生学业模拟考试
- 住宿留宿人员登记系统操作手册(旅馆前台) - 图文
- 四川大学医院管理MBA项目核心课程简介 - 图文
- 质量手册(API版) - 图文
- 53宪法课件