1

我们正在使用JAC ASN.1 编译器,遇到了我们收到无法解析的 ASN.1 消息的情况。

我查看了解析器代码,发现这是库中的一个错误。由于切换到商业解决方案不是那么容易,我们被迫分叉库并修复它。

TL;博士

在 ASN.1 解码期间是否有任何情况下您读取标签号,而不是查看您的架构是否在您所在的结构级别上具有此标签号,而是查看是否有任何嵌套元素具有此标签?

这是一个重现库中错误的小示例。您可以使用这个在线游乐场来编译模式等,并查看正常运行的解析器没有问题。

架构

基本上,它是一个包含两个元素的结构:一个选项和一个字符串,这两个元素都是可选的。该示例的关键是choice 元素包含一个标签号等于可选字符串的标签号的元素。

Example DEFINITIONS ::= BEGIN

Message ::= SEQUENCE {
    params [1] EXPLICIT Params OPTIONAL,
    confuser [2] IMPLICIT PrintableString OPTIONAL
}

Params ::= CHOICE {
    unimportant [1] IMPLICIT PrintableString,
    accident [2] IMPLICIT Accident
}

Accident ::= SEQUENCE {
    irrelevant [1] IMPLICIT PrintableString OPTIONAL
}

END

示例消息

message Message ::= {
    confuser "Foo"
}

示例消息(编码,BER)

30058203 466F6F

使用 JAC 解析器时,它将正确读取2消息中的标记号,然后遍历模式中的元素以找到与之关联的元素。但是,对于选择元素,它有一些额外的逻辑:

不是说“params 有标签 1,不是 2,所以这个值不对应”,而是说“params 有标签 1,不是 2,但它是一个选择元素,它包含一个带有标签的元素2,所以这必须是我正在寻找的元素”。

然后它接受这个类,继续解析并最终失败,因为它现在在这个类中Accident找不到标签。2

解析器逻辑中的注释说这是针对未标记选择元素的情况。但这让我感到困惑:根据我阅读的所有内容,未标记的选择元素没有默认标记,而是会被显式标记;此外,永远不能隐含地标记选择。

但是有了这些信息,我无法想象解析器中的这个逻辑有用的任何场景,我倾向于简单地删除它。但是,由于这个错误,我刚刚熟悉了 ASN.1,并且可能忽略了一些东西——是吗?

4

2 回答 2

2

有一种可能是必须查看选择成员的标签,并且选择是在没有标签的情况下添加的:

例如,如果您的定义是:

Message ::= SEQUENCE {
    params Params OPTIONAL,
    confuser [2] IMPLICIT PrintableString OPTIONAL
}

回答你的问题。

解析器逻辑中的注释说这是针对未标记选择元素的情况。但这让我感到困惑:根据我阅读的所有内容,未标记的选择元素没有默认标记,而是会被显式标记;此外,永远不能隐含地标记选择。

不,未标记的选项元素采用选项的标记。它是标记选择元素,必须显式标记并且永远不能隐式标记。


回到你的定义

Message ::= SEQUENCE {
    params [1] EXPLICIT Params OPTIONAL,
    confuser [2] IMPLICIT PrintableString OPTIONAL
}

params 组件必须有一个显式标记(既是因为您将其标记为 EXPLICIT ......也因为 X.680 的第 30.7.c 条:

30.6 如果以下任何一项成立,则标记结构指定显式标记:

...

C。使用“Tag Type”替代方案,模块的“TagDefault”值为 IMPLICIT TAGS 或 AUTOMATIC TAGS,但“Type”定义的类型是未标记的选择类型、未标记的开放类型或未标记的“DummyReference” (见 ITU-T X.683 建议书 | ISO/IEC 8824-4, 8.3)。

在这种情况下,编码是:

x.690:第 8.9.2 和 8.9.3 条

8.9.2 内容八位字节应由序列类型的 ASN.1 定义中列出的每个类型的一个数据值的完整编码组成,按照它们在定义中出现的顺序,除非该类型被引用关键字 OPTIONAL 或关键字 DEFAULT。

8.9.3 对于使用关键字 OPTIONAL 或关键字 DEFAULT 引用的类型,可以但不必存在数据值的编码。如果存在,它应出现在编码中与 ASN.1 定义中类型的外观相对应的点。

但是对于 params 组件,适用的规则首先是 8.14.2

8.14.2 如果在类型定义中未使用隐式标记(参见 ITU-T X.680 建议书 | ISO/IEC 8824-1, 30.6),则应构建编码并且内容八位字节应是完整的基础编码。

...并且只有在显式标记类型中,我们才能考虑选择 8.13 的编码

8.13 选择值的编码 选择值的编码应与所选类型的值的编码相同。

于 2014-06-11T15:46:51.180 回答
1

这里真正的问题是,尽管有指定的标记,解析器仍会查看嵌套元素。该params字段(如果存在)将始终在编码中标记为 [1]。

对于未标记的字段,查看标记的嵌套类型确实有意义。

于 2014-06-11T15:40:58.493 回答