Spec-Zone.ru › Ruby 2.4

класс OpenSSL::ASN1::ASN1Data

Родитель:
Объект

Основной класс, представляющий любой объект ASN.1. При разборе с помощью OpenSSL::ASN1.decode, помеченные значения всегда представляются экземпляром ASN1Data.

Роль ASN1Data при разборе помеченных значений

При кодировании типа ASN.1 очевидно, какой исходный тип (например, INTEGER, OCTET STRING и т.д.) имеет это значение, независимо от его пометки. Но в отличие от кодирования типа ASN.1, при его разборе невозможно определить «настоящий тип» помеченных значений. Вот почему помеченные значения обычно разбираются в экземпляры 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 STRINGS или BIT STRINGS, могут использовать эту функциональность (см. 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 (tag_class == sym_UNIVERSAL && 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-кодирования Показать исходный код
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 = 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);
    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