繁体   English   中英

ASN.1 中隐式和显式标签的编码

[英]Encoding of implicit and explicit tags in ASN.1

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

基本的例子很清楚。 普通integer,

x INTEGER ::= 5

被编码为 TLV 三元组02 01 05

x [2] IMPLICIT INTEGER ::= 5

隐式标签82替换现有标签02和 forms 另一个 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 元素吗?

“constructed”标志(第 6 位)指示标记是显式还是隐式,这是否正确? 或者我是否需要查看包装纸和被包装物的长度?

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

你问了几个问题,但每个问题都应该有一个单独的答案。

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

考虑这样一个事实:在 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)在编码中不包含标签。 尽管如此,标签的存在独立于所使用的编码规则。

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

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

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

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

Alessandro 为您提供了有关标记的出色教程。 一些快速的补充要点:

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

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

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

暂无
暂无

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

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