ASN.1编码规则详解

更新时间:2024-04-02 22:49:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

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)编码规则

从一个语法到另一个语法的映射规约。具体地说,编码规则从算法上定义了任何一组由抽象语法定义的数据值在传送语法中的表示。

下图以两个端系统通过网络交换数据为例来说明上述的一些概念。

运输实体所看到的数据是应用实体交下来的、根据一定的编码规则进行编码的二进制代码。应用实体看到的则是一个用户观点的数据,通常是结构化的信息,如文本文档或可显示的图 象信息。用户主要关心的是数据的语义。因此应用实体必须提供数据的表示方法,使得这些数据能够转换为二进制值。也就是说,应用实体必须考虑到数据的语法。

从抽象语法到传输语法,由ASN.1编译器按照编解码规则实现。

Figure 1-3 抽象语法与传输语法

其实早期的一些标准,如ASCII,它们既定义了抽象语法(比如字母A),又定义了传输语法(0x41)。ASN.1分离了这两种概念,以便可以选择一种适合要求的编解码方法。系统可以选

择编码方法以使信息传送时效率很高,或者具有很高的可靠性等等。另一方面,定义好的编码规则也会很大地节约应用协议开发人员的时间,特别是当牵涉到的数据结构很复杂的时候。当使用ASN.1的项目较多时,这种节约更加明显,因为编解码程序可以只开发一次但很多应用程序都可以用它。

我们可以看出,能将通信编解码设计与开发工作转嫁给ASN.1编译器完成。从而不必手工编写编解码器。一方面大量减少了缺陷引入,另一方面更是大大加快了系统开发速度(不用编写编解码器,也不用详细调试,维护代价也很小)。

Figure 1-4 转嫁编解码器工作给ASN.1编译器

讨论ASN.1就不得不先提到标准组织ISO和ITU。

1.2 ISO简介

国际标准组织(ISO – International Organization for Standardization)于1946年在美国成立,其负责制定众多领域的国际标准;但除电气、电子和电子工艺领域外,这些主要是IEC(International Electrotechnical Commission)负责。

ISO汇集了一百多个代表其自己国家的标准委员会(称之为NB – National Body),ANSI (American National Standard Institute)代表美国,AFNOR (Association Francaise de

NORmalisation)代表法国,BSI(British Standard Institute)代表英联邦,等等。其它一

些组织可以参加讨论,提出议案,但不能参加投票。

Figure 1-5 ISO组织结构

如Figure 1-5所示,ISO共分为172个技术委员会Technical Committee (TC)负责相应标准化领域。 所有议题都在子委员会SubCommittees中共享,Subcommittee又分为工作组Working Groups(WG)。

到1987年,著名的OSI标准就是TC97的成果,称之为“Telecommunications and Information Exchange Between Systems”。在1987年,ISO和IEC两个标准化组织一致认为都应当关注信息技术Information Technology,因此成立了一个联合技术委员会称为JTC1。JTC1的秘书处由ANSI负责。

Figure 1-6 JTC1组织结构示意图

在ASN.1标准刚刚受到关注时,基于历史原因,ASN.1主要来自于CCITT的成果,有很多提案来自CCITT。在80年代,ISO在1990年左右成为主角前,两个委员会的确有过合作。

1.3 ITU简介

国际电信联盟ITU(International Telecommunication Union)总部位于日内瓦,于1947年成为联合国的专设机构,其前身为成立于1865年的国际电报联盟(International Telegraph Union)。ITU汇集了188个代表其国家的公共电信运营商和大约450个来自私有部门称之为RPOA(Registered Private Operating Authorities)的成员(如AT&T, Bell电话等)。来自其它组织的运营商也被接收,但不具有投票权利。ITU有5个常设组织,其中一个为CCITT

(Consultative Committee on International Telephony and Telegraphy)负责电信网络,如

有线传输语音,数据和电视。在1992年ITU重组后,CCITT成为了ITU-T(ITU-Telecommunication Standardization Sector)。

ITU-T发布的建议都是以一个字母开头(每个领域一个字母编号)和一个数字作为参考号。我们通常关注的有:

? F: Non-Telephone Telecommunications Services; ? H: Audiovisual and Multimedia Systems; ? Q: Switching and Signalling;

? T: Terminals for Telematic Services;

? V: Data Communications Over the Telephone Network; ? X: Data Networks and Open System Communications; ? Z: Programming Languages.

到1992年,所有CCITT已经通过其委员会多次论证后的建议每四年发布一次(即使某些部分还未完成),其封面用不同的颜色(即黄皮书、红皮书、兰皮书和白皮书):黄色代表1976-1980,红色代表1980-1984,蓝色代表1984-1988,白色代表1988-1992。

ITU-T现在是当某个标准稳定后单独发布。此外,自1994年开始,为了防止出现不一致,ISO/IEC和ITU-T都是联合发布标准文本(各用不同的参考号)。 不一致的情况在ASN.1中出现过。

ITU-T分为研究组SG(Study Group),其中:

? SG VII,“Data Networks and Open System Communications”,课题

广泛,包括互连(比如ASN.1),X.25网络标准,X.400 Email姓名地址录标准,网络安全和网络管理等。

? SG VIII,“Terminals for Telematic Services”负责

Teletex,Videotex

和字符集等。

每个SG的工作又被划分为问题Question:其中一些相当有名,比如涉及OSI模型的Q24/7;另外一些则是对以发布标准的更为精确的更新。每个问题最终结束于一个新标准或者一个现有标准的补充。

1.4 ASN.1历史

开始于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 七层参考模型 虽然ASN.1和OSI密切相关,但实际上它也应用在很多非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

bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 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

(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中,符号的定义没有先后次序:只要能够找到该符号的定义即可,而不必关

心在使用它之前是否被定义过。如:

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)中,对数据编码使用的是三元组规则:或者称为TLV,这里type或者称为tag,它是类型的标识符,在ASN.1中每种类型的tag是唯一的。length是编码数据value的字节数。value是实际数据的编码。 I. Tags与Tagging Classes

分配给每个类型的tag实际上是一个值对:。有四种tagging class:UNIVERSAL,context-specific,APPLICATION和PRIVATE。这种方式实际提供了不同的Tag空间。在一个上下文中,如果Tagging Class不同,则相同number的两个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

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] IA5String, [1] IA5String

[0] REAL, T, CHOICE

本文来源:https://www.bwwdw.com/article/jrdr.html

Top