[0]和[3]如何在ASN1中运行?

问题描述 投票:8回答:4

我正在解码ASN1(在X.509中用于HTTPS证书)。我做得不错,但是有一件我找不到和易于理解的文档。

在此JS ASN1 parser中,您在[0]元素下看到一个[3]和一个SEQUENCE,第一个在数据中看起来像这样:A0 03 02 01 02 ...。我想知道这意味着什么以及如何对其进行解码。

另一个示例是Anatomy of an X.509 v3 Certificate,在头两个[0]元素之后有一个SEQUENCE

我不明白,A0如何适合该方案,其中标签字节的前2位是一个类,下一个是基元/构造位,其余5位应该是标签类型。 A0为10100000,这意味着标签类型值为零。

ssl-certificate asn.1
4个回答
12
投票

ASN.1 BER和DER使用ASN.1 TAGS明确标识编码流中的某些组件。 ASN.1标签共有4类:通用,应用,专用和特定于上下文。 [0]是一个上下文特定的标签,因为它前面没有标签类关键字。 UNIVERSAL保留用于ASN.1中的内置类型。大多数情况下,您会看到特定于上下文的标记,以消除包含可选元素的SEQUENCE中潜在的歧义。如果您知道收到了两个非可选项目,一个接一个,那么即使它们的标签相同,您也知道哪个是哪个。但是,如果第一个是可选的,则这两个必须具有不同的标签,否则,如果编码中仅存在一个标签,则您将无法分辨收到了哪个标签。

今天,ASN.1规范通常使用“ AUTOMATIC TAGS”,因此您不必担心消息中的这种歧义,因为SEQUENCE,SET和CHOICE的组件将自动获取以[0]开头的上下文特定的标签。 ,[1],[2]等每个组件。

您可以在http://www.oss.com/asn1/resources/books-whitepapers-pubs/asn1-books.html上找到有关ASN.1标签的更多信息,其中有两本可供下载的免费书籍。

[另一个出色的资源是http://asn1-playground.oss.com,您可以在其中使用在线编译器和编码器/解码器中的不同标签尝试ASN.1规范的变体。在那里,您可以看到标签更改对编码的影响。


15
投票

听起来您需要ASN.1标记的简介。从两个角度可以解决这个问题。 X.690定义BER / CER / DER编码规则。这样,它回答了标签如何编码的问题。 X.680定义了ASN.1本身。这样,它定义了标记的语法和规则。可以在ITU-T网站上找到这两个规范。我会给您快速的概述。

标签在BER / DER / CER中用于标识类型。它们对于区分SEQUENCE的组成部分和CHOICE的选择特别有用。

标签结合了标签类别和标签编号。标签类是UNIVERSAL,APPLICATION,PRIVATE和CONTEXT-SPECIFIC。 UNIVERSAL类基本上用于内置类型。 APPLICATION通常用于用户定义的类型。上下文特定通常用于构造类型(SEQUENCE,CHOICE,SEQUENCE OF)中的组件。从语法上讲,在ASN.1模块中指定标签时,将其写在方括号内:[tag_class tag_number];对于CONTEXT-SPECIFIC,省略tag_class。因此,[应用程序10]或[0]。

虽然每个ASN.1类型都有一个关联的标签,但从语法上讲,还有“ TaggedType”,ASN.1作者使用它来指定用于对类型进行编码的标签。基本上,TaggedType将标签前缀放在类型之前。例如:

MyType ::= SEQUENCE {
  field_with_tagged_type [0] UTF8String
}

TaggedType中的标签是显式的或隐式的。如果是显式的,则意味着我希望原始标记得到显式编码。如果是隐式的,这意味着我很高兴只对我指定的标签进行编码。在显式情况下,BER编码会导致嵌套的TLV(标签长度值):外部标签(在上面的示例中为[0]),长度,然后是另一个TLV作为值。在示例中,此内部TLV的UTF8String标记为[UNIVERSAL 12]。

标签是显式的还是隐式的,取决于您如何编写标签和标签环境。例如:

MyType2 ::= SEQUENCE {
  field_with_explicit_tag [0] EXPLICIT UTF8String OPTIONAL,
  field_with_implicit_tag [1] IMPLICIT UTF8String OPTIONAL,
  field_with_tag [2] UTF8String OPTIONAL
}

如果未指定IMPLICIT或EXPLICIT,则有一些规则定义标记是显式的还是隐式的(请参阅X.680 31)。这些规则考虑了为ASN.1模块定义的标记环境。 ASN.1模块可以将标记环境指定为“隐式标签”,“显式标签”或“自动标签”。 大致而言,如果未为标签指定IMPLICIT或EXPLICIT,则在标签环境为EXPLICIT的情况下标签是显式的,而在标签环境为IMPLICIT或AUTOMATIC的情况下则隐式的。自动标记环境与IMPLICIT标记环境基本相同,不同之处在于,自动为SEQUENCE和CHOICE类型的成员分配了唯一的标记。

注意,在上面的示例中,MyType2的三个组件都是可选的。在BER / CER / DER中,解码器将基于编码的标签(显然最好是唯一的)知道存在什么组件。


1
投票

[0]是上下文特定的标记类型,这意味着要弄清楚它赋予字段(如果设置了“ Constructed”标志)或数据值(如果未设置“ Constructed”标志)是什么意思;您必须知道它出现在什么环境中。

此外,您还需要知道发送方和接收方正在DER流中交换哪种对象,即。 “ ASN.1模块”。

假设他们正在交换证书签名请求,并且[0]作为根SEQUENCE内SEQUENCE内的第4个字段出现:

SEQUENCE
    SEQUENCE
        INTEGER 0
        SEQUENCE { ... }
        SEQUENCE { ... }
        [0] { ... }
    }
}

然后根据RFC2968(定义证书签名请求的DER内容,附录A,定义ASN.1模块),该特定字段的含义被简单定义为“属性”和“应设置构造标志” :

    attributes    [0] Attributes{{ CRIAttributes }}

[您也可以采用其他方法,看到“属性”必须是根序列内第一个序列内的第4个字段,并通过查看根序列定义将其标记为[0](第4节:“顶层输入CertificationRequest”),找到其中的CertificationRequestInfo位置,然后找到“ attributes”项在CertificationRequestInfo中的位置,最后查看如何对其进行标记。

[ASN.1非常简单,我不明白还有更多的人没有得到它。.“这只是TLV格式..”;-)


1
投票

我终于解决了这个问题,并认为我将为仍然试图理解这一点的任何人提供一些见识。在上面的示例中,我使用的是DER格式的X.509证书。我遇到了“ A0 03 02 01 02”序列,无法弄清楚它是如何转换为版本号2的。因此,如果您遇到相同的问题,请按以下步骤操作。

A0告诉您这是一个“特定于上下文的”字段,一个“构造的”标记,类型值为0x00。立即,特定于上下文的内容告诉您不要对DER / BER使用普通的类型字段。相反,假设这是X.509证书,则在RFC 5280中将类型值标记为p116。在那里您将看到四个带有标记的字段,它们分别是[0],[1],[2]和[3] ],分别代表“版本”,“ issuerUniqueID”,“ subjectUniqueID”和“扩展名”。因此,在这种情况下,值A0告诉您这是X.509上下文特定字段之一,特别是“版本”类型。这将处理“ A0”值。

正如您所期望的,“ 03”值只是您的长度。

由于已将其标识为“已构造”,因此数据应表示普通的DER / BER对象。 “ 02 01 02”是您要查找的实际版本号,表示为整数。 [02]是整数的标准BER编码,“ 01”是您的长度,“ 02”是您的值,或者在这种情况下,您的版本号。

因此,鉴于X.509定义了4种特定于上下文的类型,您应该期望在证书中的任何位置看到“ A0”,“ A1”,“ A2”和“ A3”。希望上面提供的信息现在会更有意义,并可以帮助您更好地了解这些标记代表什么。

© www.soinside.com 2019 - 2024. All rights reserved.