Class: Krypt::ASN1::Constructive

Inherits:
ASN1Data
  • Object
show all
Includes:
Enumerable
Defined in:
ext/krypt/core/krypt_asn1.c,
ext/krypt/core/krypt_asn1.c

Overview

The parent class for all constructed encodings. The value attribute of a parsed Constructive is always an Array. Attributes are the same as for ASN1Data.

SET and SEQUENCE

Most constructed encodings come in the form of a SET or a SEQUENCE. These encodings are represented by one of the two sub-classes of Constructive:

  • Krypt::ASN1::Set

  • Krypt::ASN1::Sequence

Please note that tagged sequences and sets are still parsed as instances of ASN1Data. Find further details on tagged values there.

Example - constructing a SEQUENCE

int = Krypt::ASN1::Integer.new(1)
str = Krypt::ASN1::PrintableString.new('abc')
sequence = Krypt::ASN1::Sequence.new( [ int, str ] )

Example - constructing a SET

int = Krypt::ASN1::Integer.new(1)
str = Krypt::ASN1::PrintableString.new('abc')
set = Krypt::ASN1::Set.new( [ int, str ] )

Infinite length primitive values

The only case where Constructive is used directly is for infinite length encodings of primitive values. These encodings are always constructed, with the contents of the value Array being either UNIVERSAL non-infinite length partial encodings of the actual value or again constructive encodings with infinite length (i.e. infinite length primitive encodings may be constructed recursively with another infinite length value within an already infinite length value). Each partial encoding must be of the same UNIVERSAL type as the overall encoding. The value of the overall encoding consists of the concatenation of each partial encoding taken in sequence. The value array of the outer infinite length value must end with a Krypt::ASN1::EndOfContents instance.

Example - Infinite length OCTET STRING

partial1 = Krypt::ASN1::OctetString.new("\x01")
partial2 = Krypt::ASN1::OctetString.new("\x02")
inf_octets = Krypt::ASN1::OctetString.new( [ partial1,
                                             partial2,
                                             Krypt::ASN1::EndOfContent.new ])
# The real value of inf_octets is "\x01\x02", i.e. the concatenation
# of partial1 and partial2
inf_octets.infinite_length = true
der = inf_octets.to_der
asn1 = Krypt::ASN1.decode(der)
puts asn1.infinite_length # => true

Instance Method Summary collapse

Methods inherited from ASN1Data

#<=>, #encode_to, #infinite_length, #infinite_length=, #tag, #tag=, #tag_class, #tag_class=, #to_der, #value, #value=

Constructor Details

#new(value, tag, tag_class) ⇒ ASN1Data

  • value: the value to be associated. See Primitive for the mappings

between ASN.1 types and Ruby types.

  • tag: a Number representing this value’s tag.

  • tag_class: a Symbol representing one of the four valid tag classes

:UNIVERSAL, :CONTEXT_SPECIFIC, :APPLICATION or :PRIVATE.

Creates an ASN1Data from scratch.



359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'ext/krypt/core/krypt_asn1.c', line 359

static VALUE
krypt_asn1_data_initialize(VALUE self, VALUE value, VALUE vtag, VALUE vtag_class)
{
    ID stag_class;
    int tag, tag_class, is_constructed;
    krypt_asn1_data *data;

    int_validate_tag_and_class(vtag, vtag_class);
    tag = NUM2INT(vtag);
    stag_class = SYM2ID(vtag_class);
    if (stag_class == sKrypt_TC_EXPLICIT)
	rb_raise(eKryptASN1Error, "Explicit tagging is only supported for explicit UNIVERSAL sub classes of ASN1Data");
    if (stag_class == sKrypt_TC_UNIVERSAL && tag > 30)
	rb_raise(eKryptASN1Error, "Tag too large for UNIVERSAL tag class");
    if ((tag_class = krypt_asn1_tag_class_for_id(stag_class)) == KRYPT_ERR)
        rb_raise(eKryptASN1Error, "Unknown tag class");
    is_constructed = rb_respond_to(value, sKrypt_ID_EACH);
    
    int_asn1_data_initialize(self, tag, tag_class, is_constructed, 0);

    int_asn1_data_get(self, data);
    data->update_cb = int_asn1_data_update_cb;

    int_asn1_data_set_tag(self, vtag);
    int_asn1_data_set_tag_class(self, vtag_class);
    int_asn1_data_set_infinite_length(self, Qfalse);
    int_asn1_data_set_value(self, value);

    int_asn1_data_set_modified(data, 1); /* newly created is modified by default */

    return self;
}

Instance Method Details

#each {|asn1| ... } ⇒ Object

Calls block once for each element in self, passing that element as parameter asn1. If no block is given, an enumerator is returned instead.

Example

asn1_ary.each do |asn1|
  pp asn1
end

Yields:

  • (asn1)


1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
# File 'ext/krypt/core/krypt_asn1.c', line 1136

static VALUE
krypt_asn1_cons_each(VALUE self)
{
    VALUE enumerable = krypt_asn1_data_get_value(self);

    KRYPT_RETURN_ENUMERATOR(enumerable, sKrypt_ID_EACH);

    if (rb_obj_is_kind_of(enumerable, rb_cArray))
	return rb_ary_each(krypt_asn1_data_get_value(self));
    else
	return rb_iterate(rb_each, enumerable, int_cons_each_i, Qnil);
}