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 STRING 分成较小的块,每次发送一个。这在 BER 中通过将编码的长度字节设置为零,并由此指示以下值将分块发送是可能的。不定长度编码始终是构造的。这种块流的结尾通过发送 EOC(内容结束)标签来指示。SET 和 SEQUENCE 可以使用不定长度编码,但是诸如 OCTET STRING 或 BIT STRING 之类的原始类型也可以利用此功能(参见 ITU-T X.690)。
永远不会是 nil
。一个布尔值,指示编码是否使用不定长度(在解析的情况下)或是否应使用不定长度形式(在编码的情况下)。在 DER 中,每个值都使用定长形式。但是在需要传输大量数据的场景中,可能希望提供某种流式传输支持。例如,最好将巨大的 OCTET STRING 分成较小的块,每次发送一个。这在 BER 中通过将编码的长度字节设置为零,并由此指示以下值将分块发送是可能的。不定长度编码始终是构造的。这种块流的结尾通过发送 EOC(内容结束)标签来指示。SET 和 SEQUENCE 可以使用不定长度编码,但是诸如 OCTET STRING 或 BIT STRING 之类的原始类型也可以利用此功能(参见 ITU-T X.690)。
永远不会是 nil
。一个布尔值,指示编码是否使用不定长度(在解析的情况下)或是否应使用不定长度形式(在编码的情况下)。在 DER 中,每个值都使用定长形式。但是在需要传输大量数据的场景中,可能希望提供某种流式传输支持。例如,最好将巨大的 OCTET STRING 分成较小的块,每次发送一个。这在 BER 中通过将编码的长度字节设置为零,并由此指示以下值将分块发送是可能的。不定长度编码始终是构造的。这种块流的结尾通过发送 EOC(内容结束)标签来指示。SET 和 SEQUENCE 可以使用不定长度编码,但是诸如 OCTET STRING 或 BIT STRING 之类的原始类型也可以利用此功能(参见 ITU-T X.690)。
携带 ASN.1 类型的值。有关 ASN.1 数据类型和 Ruby 类之间的映射,请参阅 Constructive
和 Primitive
。
公共类方法
来源
# File ext/openssl/lib/openssl/asn1.rb, line 66 def initialize(value, tag, tag_class) raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol) @tag = tag @value = value @tag_class = tag_class @indefinite_length = false end
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
公共实例方法
来源
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); } }
将此 ASN1Data
编码为 DER 编码的 String
值。结果是 DER 编码的,但可能存在不定长度形式。严格的 DER 中不允许不定长度形式,因此严格来说,这种编码的结果将是 BER 编码。