类 OpenSSL::ASN1::ASN1Data

表示任何 ASN.1 对象的顶级类。当通过 ASN1.decode 解析时,带标签的值始终由 ASN1Data 的实例表示。

ASN1Data 在解析带标签值中的作用

在编码 ASN.1 类型时,无论其标签如何,其原始类型(例如 INTEGER、OCTET STRING 等)都是明确的。但与编码 ASN.1 类型时相反,在解析它们时,无法推断带标签值的“真实类型”。这就是为什么带标签的值通常解析为 ASN1Data 实例,但对于隐式和显式标签的结果不同。

解析隐式带标签值的示例

隐式 1 标签的 INTEGER 值将被解析为一个 ASN1Data,其中

这意味着需要后续的解码步骤才能完全解码隐式带标签的值。

解析显式带标签值的示例

显式 1 标签的 INTEGER 值将被解析为一个 ASN1Data,其中

示例 - 解码隐式带标签的 INTEGER

int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT) # implicit 0-tagged
seq = OpenSSL::ASN1::Sequence.new( [int] )
der = seq.to_der
asn1 = OpenSSL::ASN1.decode(der)
# pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
#              @indefinite_length=false,
#              @tag=16,
#              @tag_class=:UNIVERSAL,
#              @tagging=nil,
#              @value=
#                [#<OpenSSL::ASN1::ASN1Data:0x87326f4
#                   @indefinite_length=false,
#                   @tag=0,
#                   @tag_class=:CONTEXT_SPECIFIC,
#                   @value="\x01">]>
raw_int = asn1.value[0]
# manually rewrite tag and tag class to make it an UNIVERSAL value
raw_int.tag = OpenSSL::ASN1::INTEGER
raw_int.tag_class = :UNIVERSAL
int2 = OpenSSL::ASN1.decode(raw_int)
puts int2.value # => 1

示例 - 解码显式带标签的 INTEGER

int = OpenSSL::ASN1::Integer.new(1, 0, :EXPLICIT) # explicit 0-tagged
seq = OpenSSL::ASN1::Sequence.new( [int] )
der = seq.to_der
asn1 = OpenSSL::ASN1.decode(der)
# pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
#              @indefinite_length=false,
#              @tag=16,
#              @tag_class=:UNIVERSAL,
#              @tagging=nil,
#              @value=
#                [#<OpenSSL::ASN1::ASN1Data:0x87326f4
#                   @indefinite_length=false,
#                   @tag=0,
#                   @tag_class=:CONTEXT_SPECIFIC,
#                   @value=
#                     [#<OpenSSL::ASN1::Integer:0x85bf308
#                        @indefinite_length=false,
#                        @tag=2,
#                        @tag_class=:UNIVERSAL
#                        @tagging=nil,
#                        @value=1>]>]>
int2 = asn1.value[0].value[0]
puts int2.value # => 1

属性

indefinite_length[RW]

从不为 nil。一个布尔值,指示编码是否使用不定长(在解析的情况下)或是否应使用不定长形式(在编码的情况下)。在 DER 中,每个值都使用定长形式。但在需要传输大量数据的情况下,可能需要某种流支持。例如,巨大的 OCTET STRING 最好以较小的块发送,每次发送一个块。这可以通过在 BER 中将编码的长度字节设置为零来实现,从而指示后续值将以块的形式发送。不定长编码始终是构造的。此类块流的结束通过发送 EOC(内容结束)标签来指示。SET 和 SEQUENCE 可以使用不定长编码,但原始类型(例如 OCTET STRING 或 BIT STRING)也可以利用此功能(参见 ITU-T X.690)。

infinite_length[RW]

从不为 nil。一个布尔值,指示编码是否使用不定长(在解析的情况下)或是否应使用不定长形式(在编码的情况下)。在 DER 中,每个值都使用定长形式。但在需要传输大量数据的情况下,可能需要某种流支持。例如,巨大的 OCTET STRING 最好以较小的块发送,每次发送一个块。这可以通过在 BER 中将编码的长度字节设置为零来实现,从而指示后续值将以块的形式发送。不定长编码始终是构造的。此类块流的结束通过发送 EOC(内容结束)标签来指示。SET 和 SEQUENCE 可以使用不定长编码,但原始类型(例如 OCTET STRING 或 BIT STRING)也可以利用此功能(参见 ITU-T X.690)。

tag[RW]

一个 Integer,表示此 ASN1Data 的标签号。从不为 nil

tag_class[RW]

一个 Symbol,表示此 ASN1Data 的标签类。从不为 nil。有关可能的值,请参见 ASN1Data

value[RW]

承载 ASN.1 类型的 value。请参阅 ConstructivePrimitive,了解 ASN.1 数据类型和 Ruby 类之间的映射。

公共类方法

OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) → ASN1Data click to toggle source

value: 请查看 ConstructivePrimitive,了解 Ruby 类型如何映射到 ASN.1 类型,反之亦然。

tag: 一个 Integer,指示标签号。

tag_class: 一个 Symbol,指示标签类。请参阅 ASN1,了解可能的值。

示例

asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
static VALUE
ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
{
    if(!SYMBOL_P(tag_class))
        ossl_raise(eASN1Error, "invalid tag class");
    ossl_asn1_set_tag(self, tag);
    ossl_asn1_set_value(self, value);
    ossl_asn1_set_tag_class(self, tag_class);
    ossl_asn1_set_indefinite_length(self, Qfalse);

    return self;
}

公共实例方法

to_der → DER 编码的 String click to toggle source

将此 ASN1Data 编码为 DER 编码的 String 值。结果是 DER 编码的,除了可能存在不定长形式。不定长形式在严格的 DER 中不允许,因此严格来说,此类编码的结果将是 BER 编码。

static VALUE
ossl_asn1data_to_der(VALUE self)
{
    VALUE value = ossl_asn1_get_value(self);

    if (rb_obj_is_kind_of(value, rb_cArray))
        return ossl_asn1cons_to_der(self);
    else {
        if (RTEST(ossl_asn1_get_indefinite_length(self)))
            ossl_raise(eASN1Error, "indefinite length form cannot be used " \
                       "with primitive encoding");
        return ossl_asn1prim_to_der(self);
    }
}