class OpenSSL::ASN1::ASN1Data
表示任何 ASN.1 对象的顶级类。当由 ASN1.decode 解析时,带标签的值始终由 ASN1Data 的实例表示。
ASN1Data 在解析带标签的值中的作用
在编码 ASN.1 类型时,其原始类型(例如 INTEGER、OCTET STRING 等)是固有的,与其标签无关。但与 ASN.1 类型要被编码时不同,在解析它们时,无法推断带标签值的“真实类型”。这就是为什么带标签的值通常被解析为 ASN1Data 实例,但隐式标签和显式标签的结果不同。
隐式标签值解析示例
隐式 1 标签的 INTEGER 值将被解析为 ASN1Data,其中:
-
tag 等于 1
-
tag_class 等于
:CONTEXT_SPECIFIC -
value 等于一个
String,其中包含 INTEGER 的原始编码。
这意味着需要后续的解码步骤来完全解码隐式标签的值。
显式标签值解析示例
显式 1 标签的 INTEGER 值将被解析为 ASN1Data,其中:
-
tag 等于 1
-
tag_class 等于
:CONTEXT_SPECIFIC -
value 等于一个
Array,其中包含一个元素,即OpenSSL::ASN1::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
属性
永远不为 nil。一个布尔值,指示编码是否使用不定长度(在解析时)或是否应使用不定长度形式(在编码时)。在 DER 中,所有值都使用定长形式。但在需要传输大量数据的情况下,可能希望提供某种流式支持。例如,巨大的 OCTET STRINGs 最好分成小块传输,一次一块。这在 BER 中可以通过将编码的长度字节设置为零来实现,从而指示后续值将分块发送。不定长度编码始终是构造的。这种块流的结束通过发送 EOC(End of Content)标签来指示。SETs 和 SEQUENCEs 可以使用不定长度编码,但像 OCTET STRINGS 或 BIT STRINGS 这样的原语类型也可以利用此功能(参见 ITU-T X.690)。
永远不为 nil。一个布尔值,指示编码是否使用不定长度(在解析时)或是否应使用不定长度形式(在编码时)。在 DER 中,所有值都使用定长形式。但在需要传输大量数据的情况下,可能希望提供某种流式支持。例如,巨大的 OCTET STRINGs 最好分成小块传输,一次一块。这在 BER 中可以通过将编码的长度字节设置为零来实现,从而指示后续值将分块发送。不定长度编码始终是构造的。这种块流的结束通过发送 EOC(End of Content)标签来指示。SETs 和 SEQUENCEs 可以使用不定长度编码,但像 OCTET STRINGS 或 BIT STRINGS 这样的原语类型也可以利用此功能(参见 ITU-T X.690)。
承载 ASN.1 类型的值。有关 ASN.1 数据类型和 Ruby 类之间的映射,请参阅 Constructive 和 Primitive。
Public Class Methods
Source
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;
}
value:请查看 Constructive 和 Primitive,了解 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
Public Instance Methods
Source
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);
}
}