繁体   English   中英

ASN.1 序列混淆

[英]ASN.1 Sequence Confusion

我正在研究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
}

该模式的一个实例可能是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 或关键字 DEFAULT 引用的类型,数据值的编码可以,但不是必须的。 如果存在,它应出现在编码中对应于 ASN.1 定义中类型出现的点。

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

假设你写了以下内容:

R DEFINITIONS AUTOMATIC TAGS ::=

 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.", city "New York", state "NY", zipcode "12345" }

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

(在 ASN.1 中还有一个叫做“类”的东西,但它是完全不同的东西。)

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

ASN.1 文件通常包含这样的序列类型的类型分配(类型定义):

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 );

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM