ASN.1序列混淆

时间:2013-07-17 21:06:53

标签: asn.1

我正在研究ASN.1的语法,我在网上阅读了很多相关资料:

http://www.itu.int/rec/T-REC-X.690-200811-I/en
http://luca.ntop.org/Teaching/Appunti/asn1.html
http://www.obj-sys.com/asn1tutorial/node11.html

我对ASN.1 SEQUENCE类型的编码感到困惑。一般来说,我意识到SEQUENCE基本上是一个聚合 - 我们在大多数编程语言中称之为OBJECT或INSTANCE。它基本上是名称/值对的列表,类似于JSON对象。但与JSON对象不同,ASN.1 SEQUENCE具有隐式SCHEMA,因为它是“类”的实例

因此,SEQUENCE的类/架构可能类似于:

{
  name  UTF8String
  age   INTEGER
}

该架构的 INSTANCE 可以是SEQUENCE

{
  "John Smith"
  42
}

但是我对如何在实际BER编码中区分CLASS和INSTANCE感到困惑。事实上,我很困惑,我甚至不确定ASN.1 SEQUENCE是否应该是类定义或类的实例。

文档似乎暗示它是一个实例:

  

8.9 序列值编码

     

8.9.1 应构建序列值的编码。

     

8.9.2 内容八位字节应包含ASN.1定义中列出的每种类型的一个数据值的完整编码   序列类型,按其出现的顺序排列   定义,除非使用关键字OPTIONAL引用类型   或关键字DEFAULT。

     

8.9.3 对于使用关键字OPTIONAL或关键字引用的类型,可以(但不一定)存在数据值的编码   默认。如果存在,它将出现在该点的编码中   对应于ASN.1定义中类型的外观。

所以似乎SEQUENCE只是一个数据值列表,它必须对应于某个模式(类)。但是ASN.1没有CLASS类型,那么你如何得到实际的类,所以你知道任何给定的SEQUENCE是什么类的实例?

2 个答案:

答案 0 :(得分:1)

假设您编写以下内容:

R定义自动标签:: =

BEGIN

USPostalAddress :: = SEQUENCE {

  street     IA5String,

  city       IA5String,

  state      IA5String (SIZE (2)) (FROM("A".."Z")),

  zipcode    IA5String (SIZE (5)) (FROM("0".."9"))

}

END

BEGIN和END之间的部分称为“类型分配”。 “USPostalAddress”是(用户定义的)“类型”的名称。通过编写上述内容,您已指定了用户定义的类型,并为其指定了名称。每个SEQUENCE构造(例如,上面的SEQUENCE构造)是“类型”。它是一种复杂的类型,因为它包含一个或多个“字段”,每个字段都有自己的类型。上述类型的可能“值”表示如下:

{street“1234 Main St.”,城市“纽约”,州“NY”,邮政编码“12345”}

我们只讨论类型及其值,而不是类和实例。就像你可以有一个INTEGER(0..15)类型,其值是0到15之间的整数,你可以有一个SEQUENCE类型,其值是较低级别值的排列。上面的序列类型是您可以在ASN.1中定义的数据结构(“类型”)的一个非常简单的示例。

(在ASN.1中也有一种称为“类”的东西,但它完全不同。)

在ASN.1中,协议消息通常被指定为顶级类型(通常它们是SEQUENCE或CHOICE类型)。特定的“消息值”是顶级类型的值。如果手中有顶级类型的值,则可以使用标准编码规则(BER,PER等)将该值编码为位流。当您从网络接收到一个比特流,您知道它是以BER,PER等编码的特定ASN.1类型的值时,您可以解码这些比特并获得原始值。

答案 1 :(得分:0)

ASN.1文件通常包含类型赋值(类型定义),如SEQUENCE类型:

myMessage ::= SEQUENCE
{
    a INTEGER(0..100),
    b INTEGER
}

ASN.1文件中的SEQUENCE类型可以被认为与C ++ / java中的类或C中的结构定义相同。

SEQUENCE的实例可以采用编码格式(BER,PER,DER等)或程序内的本地格式(对象/变量)。

示例如何在C代码中实现这些:

struct myMessage_t          
{
  int a;
  int b;
};

char buffer[1000];   // BER encoded instance will be stored to this buffer
myMessage_t msg;     // this is the local instance

msg.a = 1;
msg.b = 2;

size_t berLen = berEncode_myMessage( &msg, buffer, sizeof(buffer) );

解码方面:

myMessage_t msg2;            
berDecode_myMessage( buffer, berLen, &msg2 );
assert( msg2.a == 1 );

在解码之前,您通常知道什么是顶级类型的编码实例。