Spec-Zone.ru › Ruby 2.2

класс 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

Атрибуты

infinite_length[RW]

Никогда nil. Boolean указывает, было ли кодирование бесконечной длины (при разборе) или должно использоваться кодирование бесконечной длины (при кодировании). В DER каждое значение имеет конечную длину. Но в сценариях, где необходимо передавать большие объёмы данных, может быть желательно иметь поддержку потоковой передачи. Например, огромные OCTET STRING лучше отправлять частями, по частям. Это возможно в BER, устанавливая байты длины кодирования в ноль и тем самым указывая, что последующее значение будет отправлено частями. Кодирования бесконечной длины всегда строятся. Конец такого потока частей указывается отправкой тега EOC (Конец содержимого). Множества и последовательности могут использовать кодирование бесконечной длины, но также и примитивные типы, такие как, например, OCTET STRING или BIT STRING, могут использовать эту функциональность (см. ITU-T X.690).

tag[RW]

Число, представляющее номер тега этого ASN1Data. Никогда nil.

tag_class[RW]

Класс, представляющий класс тега этого ASN1Data. Никогда nil. См. ASN1Data для возможных значений.

value[RW]

Содержит значение типа ASN.1. См. Constructive и Primitive для отображений между типами данных ASN.1 и классами Ruby.

Публичные методы класса

OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) → ASN1Data Показать исходный код
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

Публичные методы экземпляра

to_der → DER-encoded String Показать исходный код
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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API