3

我试图了解 IMPLICIT 和 EXPLICIT 标签实际上是如何以 DER 二进制形式编码的。

基本的例子很清楚。纯整数,

x INTEGER ::= 5

被编码为 TLV 三元组02 01 05。在

x [2] IMPLICIT INTEGER ::= 5

隐式标签82替换现有标签02并形成另一个 TLV: 82 01 05,并在

x [3] EXPLICIT INTEGER ::= 5

在原始 TLV 周围添加了一个包装器:A3 03 02 01 05.

现在我在看一个更复杂的案例

30 42 A1 40 30 0D 82 0B  77 77 77 2E 62 61 64 2E
6F 72 67 30 09 82 07 62  61 64 2E 63 6F 6D 30 0D
81 0B 62 61 64 40 62 61  64 2E 6F 72 67 30 09 81
07 62 61 64 2E 63 6F 6D  30 0A 87 08 0A 00 00 00
FF 00 00 00

它被解码成

SEQUENCE {
  [1] {
    SEQUENCE {
      [2] www.bad.org
    }
    SEQUENCE {
      [2] bad.com
    }
    SEQUENCE {
      [1] bad@bad.org
    }
    SEQUENCE {
      [1] bad.com
    }
    SEQUENCE {
      [7] 0A000000FF000000
    }
  }
}

我的问题是,我怎么知道A1是一个隐式标签[1] IMPLICIT SEQUENCE,它取代了原始标签10,并且包含五个 TLV 元素(序列),还是一个包含这五个元素的显式标签?是什么A1

显式标签可以包装多个 TLV 元素吗?

“构造”标志(位 6)指示标签是显式还是隐式,这是否正确?还是我需要查看包装纸的长度和被包裹的东西?

我不假设二进制数据是正确的,所以另一种可能性是A1 40环绕以下序列30 0D ...,长度不匹配并且必须拒绝数据。

4

2 回答 2

8

你问了几个问题,但每个问题都值得单独回答。

标签本身不是隐含的或显式的。“标记”(将标记添加到类型的操作)是隐式的或显式的。

考虑在 ASN.1 中每个基本类型(例如,INTEGER、BOOLEAN)或除 CHOICE(例如,SEQUENCE)之外的类型构造函数都有一个内置的“通用”标签。例如,INTEGER 类型具有内置标签 UNIVERSAL 2,OBJECT IDENTIFIER 类型具有内置标签 UNIVERSAL 6,每个 SEQUENCE 类型都有内置标签 UNIVERSAL 16,依此类推。这并非特定于 BER/DER。它是类型本身的属性。

当一种类型作为另一种类型的组成部分出现时(例如,SEQUENCE 或 CHOICE),它通常(但不总是)被分配另一个标签。新标签可以替换现有标签,也可以插入现有标签之前。这就是隐式标记和显式标记。在隐式标记中,新标记替换其应用类型的现有标记。在显式标记中,新标记以现有标记为前缀。这也不是 BER/DER 特有的,它是 ASN.1 的一个特性。一些编码规则(BER、DER 和 OER 在有限范围内)使用编码中的标签,而其他编码规则(PER、JER)不包括编码中的标签。不过,标签的存在独立于所使用的编码规则。

给定类型是否使用隐式或显式标记取决于几件事。首先,模块头中指定了默认标记(显式标记、隐式标记、自动标记),它为模块中存在的类型建立了默认标记模式。(“默认默认值”是显式标记。)其次,可以通过在 ']' 之后使用关键字 IMPLICIT 或 EXPLICIT 来覆盖特定类型的模块的默认标记。第三,在某些情况下,标记必须是明确的。

如果您在模块标题中指定 AUTOMATIC TAGS,则进程将生成并应用连续标签,从“上下文特定”0 开始,到每个序列类型、集合类型和选择类型的每个组件,不包含文字在其任何组件中添加标签。自动标记过程应用隐式标记,这意味着每个生成的标记都将替换现有标记。

有一些限制和一些特殊情况。一个是 CHOICE 类型没有自己的通用标记,因此不可能将隐式标记应用于前面没有文字标记的 CHOICE 类型(没有要替换的标记)。如果您不使用 AUTOMATIC TAGS 并且不向选择类型添加新标签,则选择类型将保持没有自己的标签。在 BER/DER 中,解码器仍然可以通过查看即将到来的标签来检测未标记选择类型的存在,该标签属于存在的选择选项。

上面表明,BER/DER 解码器如何解释编码中的下一个标签不会有歧义。标记过程为模块中的每个类型(包括复杂类型的组件类型)分配明确定义的标记(通常是一个或两个标记,或者在未标记选择类型的情况下可能没有标记)。如上所述,这些标签是 ASN.1 模式中存在的每种类型的属性。在 BER 和 DER 中,编码器将只插入它正在编码的每个值的类型的所有标签。如果值的类型有一个标签,编码器将产生一个 TLV。如果值的类型有两个标签,编码器会产生两个嵌套的 TLV。其实很简单。解码器将知道会发生什么。

于 2020-09-22T04:30:19.673 回答
2

Alessandro 为您提供了关于标记的出色教程。一些快速的附加点:

通用 BER 解码器可以将 BER 数据解码为 TLV 层次结构,但您通常需要有模式才能知道如何将其与 ASN.1 类型相关联。

标签应用于类型,因此,不,您不能添加显式标签来包装多个 TLV 元素。它将包装一个 TLV。

构造的标志告诉您 TLV 中的 V(值)本身是否是 TLV。某些类型(例如 BIT STRING)可以以构造形式或原始形式进行编码。当一个类型被显式标记时,它总是会产生一个带有构造标志集的 TLV,但这并不是唯一一次使用构造标志。

于 2020-09-22T13:38:40.220 回答