класс OpenSSL::ASN1::ASN1Data
Основной класс, представляющий любой объект ASN.1. При разборе с помощью OpenSSL::ASN1.decode, помеченные значения всегда представлены экземпляром ASN1Data.
Роль ASN1Data при разборе помеченных значений
При кодировании типа ASN.1 явно понятно, какой исходный тип (например, INTEGER, OCTET STRING и т.д.) имеет это значение, независимо от его пометок. Но в отличие от кодирования, при разборе невозможно определить «реальный тип» помеченных значений. Именно поэтому помеченные значения обычно разбираются в экземпляры ASN1Data, но с разными результатами для неявных и явных пометок.
Пример разбора неявного помеченного значения
Неявно помеченное значение INTEGER со значением 1 будет разобрано как ASN1Data со
-
tagравным 1 -
tag_classравным:CONTEXT_SPECIFIC -
valueравнымString, который содержит исходное кодирование INTEGER.
Это подразумевает, что для полного разбора неявных помеченных значений требуется дополнительный этап декодирования.
Пример разбора явного помеченного значения
Явно помеченное значение INTEGER со значением 1 будет разобрано как 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 # @infinite_length=false, # @tag=16, # @tag_class=:UNIVERSAL, # @tagging=nil, # @value= # [#<OpenSSL::ASN1::ASN1Data:0x87326f4 # @infinite_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 # @infinite_length=false, # @tag=16, # @tag_class=:UNIVERSAL, # @tagging=nil, # @value= # [#<OpenSSL::ASN1::ASN1Data:0x87326f4 # @infinite_length=false, # @tag=0, # @tag_class=:CONTEXT_SPECIFIC, # @value= # [#<OpenSSL::ASN1::Integer:0x85bf308 # @infinite_length=false, # @tag=2, # @tag_class=:UNIVERSAL # @tagging=nil, # @value=1>]>]> int2 = asn1.value[0].value[0] puts int2.value # => 1
Атрибуты
Никогда nil. Boolean указывает, было ли кодирование бесконечной длины (при разборе) или должно использоваться кодирование бесконечной длины (при кодировании). В DER каждое значение имеет конечную длину. Но в сценариях, где необходимо передавать большие объёмы данных, может быть желательно иметь поддержку потоковой передачи. Например, огромные OCTET STRING лучше отправлять частями, по частям. Это возможно в BER, устанавливая байты длины кодирования в ноль и тем самым указывая, что последующее значение будет отправлено частями. Кодирования бесконечной длины всегда строятся. Конец такого потока частей указывается отправкой тега EOC (Конец содержимого). Множества и последовательности могут использовать кодирование бесконечной длины, но также и примитивные типы, такие как, например, OCTET STRING или BIT STRING, могут использовать эту функциональность (см. ITU-T X.690).
Число, представляющее номер тега этого ASN1Data. Никогда nil.
Содержит значение типа ASN.1. См. Constructive и Primitive для отображений между типами данных ASN.1 и классами Ruby.
Публичные методы класса
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");
if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
ossl_raise(eASN1Error, "tag number for Universal too large");
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
ossl_asn1_set_tag_class(self, tag_class);
ossl_asn1_set_infinite_length(self, Qfalse);
return self;
} value: Пожалуйста, обратитесь к Constructive и Primitive, чтобы увидеть, как типы Ruby сопоставляются с типами ASN.1 и наоборот.
tag: Number, указывающий номер тега.
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, der, inf_length;
int tag, tag_class, is_cons = 0;
long length;
unsigned char *p;
value = ossl_asn1_get_value(self);
if(rb_obj_is_kind_of(value, rb_cArray)){
is_cons = 1;
value = join_der(value);
}
StringValue(value);
tag = ossl_asn1_tag(self);
tag_class = ossl_asn1_tag_class(self);
inf_length = ossl_asn1_get_infinite_length(self);
if (inf_length == Qtrue) {
is_cons = 2;
}
if((length = ossl_asn1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0)
ossl_raise(eASN1Error, NULL);
der = rb_str_new(0, length);
p = (unsigned char *)RSTRING_PTR(der);
ossl_asn1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class);
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
p += RSTRING_LEN(value);
ossl_str_adjust(der, p);
return der;
} Кодирует этот ASN1Data в строку DER-кодированного значения. Результат DER-кодирован, за исключением возможности кодирования бесконечной длины. Кодирования бесконечной длины не допускаются в строгом DER, поэтому строго говоря, результатом такого кодирования будет BER-кодирование.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.