简体   繁体   English

我需要一个例子来理解ASN.1中的隐式标记

[英]I need an example to understand Implicit Tagging in ASN.1

I have been going through the following tutorial 我一直在阅读以下教程

http://www.obj-sys.com/asn1tutorial/node12.html http://www.obj-sys.com/asn1tutorial/node12.html

Can you help me understand implicit tagging with an example? 你能用一个例子来帮助我理解隐式标记吗?

In ASN.1 tagging, in fact, serves two purposes: typing and naming. 事实上,在ASN.1标记中,有两个目的:打字和命名。 Typing means it tells an en-/decoder what kind of data type that is (is it a string, an integer, a boolean, a set, etc.), naming means that if there are multiple fields of the same type and some (or all of them) are optional, it tells the en-/decoder for which field that value is. 键入意味着它告诉en / /解码器是什么类型的数据类型(它是字符串,整数,布尔值,集合等),命名意味着如果有多个相同类型的字段和一些(或者所有这些都是可选的,它告诉en- /解码器该值是哪个字段。

If you compare ASN.1 to, let's say, JSON, and you look at the following JSON data: 如果你比较ASN.1,比如JSON,你看看下面的JSON数据:

"Image": {
    "Width":  800,
    "Height": 600,
    "Title":  "View from 15th Floor"
}

You'll notice that in JSON every field is always explicitly named ("Image", "Width", "Height", "Title") and either explicitly or implicitly typed ("Title" is a string, because its value is surrounded by quotes, "Width" is an integer, because it has no quotes, only digits, it's not "null", "true" or "false", and it has no decimal period). 你会注意到在JSON中,每个字段总是被明确命名(“Image”,“Width”,“Height”,“Title”)并且显式或隐式地键入(“Title”是一个字符串,因为它的值被包围引号,“宽度”是一个整数,因为它没有引号,只有数字,它不是“null”,“true”或“false”,并且它没有小数句点。

In ASN.1 this piece of data would be: 在ASN.1中,这条数据将是:

Image ::= SEQUENCE { 
    Width  INTEGER,
    Height INTEGER,
    Title  UTF8String
 }

This will work without any special tagging, here only the universal tags are required. 这将没有任何特殊标记,这里只需要通用标签。 Universal tags don't name data, they just type data, so en-/decoder know that the first two values are integers and the last one is a string. 通用标签不命名数据,它们只是键入数据,因此en- / decoder知道前两个值是整数,最后一个是字符串。 That the first integer is Width and the second one is Height doesn't need to be encoded in the byte stream, it is defined by their order (sequences have a fixed order, sets don't. On the page you referred to sets are being used). 第一个整数是Width而第二个是Height不需要在字节流中编码,它是由它们的顺序定义的(序列有固定的顺序,设置不是。在你引用的页面上是正在使用)。

Now change the schema as follows: 现在更改架构如下:

Image ::= SEQUENCE { 
    Width  INTEGER OPTIONAL,
    Height INTEGER OPTIONAL,
    Title  UTF8String
 }

Okay, now we have a problem. 好的,现在我们遇到了问题。 Assume that the following data is received: 假设收到以下数据:

INTEGER(750), UTF8String("A funny kitten")

What is 750? 什么是750? Width or Height? 宽度还是高度? Could be Width (and Height is missing) or could be Height (and Width is missing), both would look the same as a binary stream. 可能是宽度(和高度缺失)或可能是高度(并且缺少宽度),两者看起来都与二进制流相同。 In JSON that would be clear as every piece of data is named, in ASN.1 it isn't. 在JSON中,每个数据都被命名,因为在ASN.1中它不是。 Now a type alone isn't enough, now we also need a name. 现在单独一种类型是不够的,现在我们还需要一个名字。 That's where the non-universal tags enter the game. 这就是非通用标签进入游戏的地方。 Change it to: 将其更改为:

Image ::= SEQUENCE { 
    Width  [0] INTEGER OPTIONAL,
    Height [1] INTEGER OPTIONAL,
    Title  UTF8String
 }

And if you receive the following data: 如果您收到以下数据:

[1]INTEGER(750), UTF8String("A funny kitten")

You know that 750 is the Height and not the Width (there simply is no Width). 你知道750是高度而不是宽度(根本没有宽度)。 Here you declare a new tag (in that case a context specific one) that serves two purposes: It tells the en-/decoder that this is an integer value (typing) and it tells it which integer value that is (naming). 在这里,您声明一个新标记(在这种情况下是一个特定于上下文的标记),它有两个目的:它告诉en- /解码器这是一个整数值(输入),它告诉它是哪个整数值(命名)。

But what is the difference between implicit and explicit tagging? 但隐式标记和显式标记之间有什么区别? The difference is that implicit tagging just names the data, the en-/decoder needs to know the type implicitly for that name , while explicit tagging names and explicitly types the data . 区别在于隐式标记只是命名数据,en- /解码器需要隐式知道该名称的类型 ,而显式标记名称并显式键入数据

If tagging is explicit, the data will be sent as: 如果标记是显式的,则数据将作为以下内容发送:

[1]INTEGER(xxx), UTF8String(yyy)

so even if a decoder has no idea that [1] means Height, it knows that the bytes "xxx" are to be parsed/interpreted as an integer value. 因此,即使解码器不知道[1]意味着高度,它也知道字节“xxx”将被解析/解释为整数值。 Another important advantage of explicit tagging is that the type can be changed in the future without changing the tag. 显式标记的另一个重要优点是可以在将来更改类型而无需更改标记。 Eg 例如

Length ::= [0] INTEGER

can be changed to 可以改为

Length ::= [0] CHOICE { 
    integer INTEGER,
    real    REAL 
}

Tag [0] still means length, but now length can either be an integer or a floating point value. Tag [0]仍然表示长度,但现在length可以是整数或浮点值。 Since the type is encoded explicitly, decoders will always know how to correctly decode the value and this change is thus forward and backward compatible (at least at decoder level, not necessarily backward compatible at application level). 由于类型是明确编码的,因此解码器将始终知道如何正确地解码该值,因此这种变化是向前和向后兼容的(至少在解码器级别,不一定在应用级别向后兼容)。

If tagging is implicit, the data will be sent as: 如果标记是隐式的,则数据将作为以下内容发送:

[1](xxx), UTF8String(yyy)

A decoder that doesn't know what [1] is, will not know the type of "xxx" and thus cannot parse/interpret that data correctly. 不知道[1]是什么的解码器将不知道“xxx”的类型,因此无法正确地解析/解释该数据。 Unlike JSON, values in ASN.1 are just bytes. 与JSON不同,ASN.1中的值只是字节。 So "xxx" may be one, two, three or maybe four bytes and how to decode those bytes depends on their data type, which is not provided in the data stream itself. 因此“xxx”可以是一个,两个,三个或可能是四个字节,并且如何解码这些字节取决于它们的数据类型,这在数据流本身中没有提供。 Also changing the type of [1] will break existing decoders for sure. 同样改变[1]的类型肯定会破坏现有的解码器。

Okay, but why would anyone use implicit tagging? 好的,但为什么有人会使用隐式标记? Isn't it better to always use explicit tagging? 总是使用显式标记不是更好吗? With explicit tagging, the type must also be encoded in the data stream and this will require two additional bytes per tag. 使用显式标记时,类型也必须在数据流中进行编码,这将需要每个标记两个额外的字节。 For data transmissions containing several thousand (maybe even millions of) tags and where maybe every single byte counts (very slow connection, tiny packets, high packet loss, very weak processing devices) and where both sides know all custom tags anyway, why wasting bandwidth, memory, storage and/or processing time for encoding, transmitting and decoding unnecessary type information? 对于包含数千(甚至数百万)个标签的数据传输,可能每个字节都很重要(连接速度很慢,数据包很小,数据包损耗很大,处理设备非常弱),双方都知道所有自定义标签,为什么要浪费带宽用于编码,传输和解码不必要类型信息的存储器,存储器和/或处理时间?

Keep in mind that ASN.1 is a rather old standard and it was intended to achieve a highly compact representation of data at a time where network bandwidth was very expensive and processors several hundred times slower than today. 请记住,ASN.1是一个相当古老的标准,它的目的是在网络带宽非常昂贵且处理器比现在慢几百倍的时候实现高度紧凑的数据表示。 If you look at all the XML and JSON data transfers of today, it seems ridiculous to even think about saving two bytes per tag. 如果你看看今天的所有XML和JSON数据传输,甚至考虑为每个标签保存两个字节似乎是荒谬的。

I find this thread to be clear enough, it also contains (small) examples even tough they are quite 'extreme' examples at that. 我发现这个帖子足够清楚,它还包含(小)例子甚至很难,它们是非常“极端”的例子。 A more 'realistic' examples using IMPLICIT tags can be found in this page . 此页面中可以找到使用IMPLICIT标签的更“实际”的示例。

Using the accepted answer as an example of encoding: 使用接受的答案作为编码示例:

Image ::= SEQUENCE { 
    Width  INTEGER,
    Height INTEGER,
    Title  UTF8String
}

An example of encoding would be: 编码的一个例子是:

在此输入图像描述

The internal sequence breaks down into: 内部序列分解为:

在此输入图像描述

Explicit Optional 明确的可选

If you then have EXPLICIT OPTIONAL values: 如果您具有EXPLICIT OPTIONAL值:

Image ::= SEQUENCE { 
    Width  [0] EXPLICIT INTEGER OPTIONAL,
    Height [1] EXPLICIT INTEGER OPTIONAL,
    Title  UTF8String
}

The encoded sequence might be: 编码序列可能是:

  • SEQUENCE 30 15 A1 02 02 02 EE 0C 0E 41 20 66 75 6E 6E 79 20 6B 69 74 74 65 6E (21-bytes) SEQUENCE 30 15 A1 02 02 02 EE 0C 0E 41 20 66 75 6E 6E 79 20 6B 69 74 74 65 6E (21字节)

And the internal sequence breaks down into: 并且内部序列分解为:

  • CONTEXT[1] INTEGER : A1 02 02 02 EE 750 (2-bytes) 语境[1] INTEGERA1 02 02 02 EE 750(2字节)
  • UTF8STRING : 0C 0E 41 20 66 75 6E 6E 79 20 6B 69 74 74 65 6E "A funny kitten" (14-bytes) UTF8STRING0C 0E 41 20 66 75 6E 6E 79 20 6B 69 74 74 65 6E “一只有趣的小猫”(14字节)

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

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