module RASN1::Types

This modules is a namesapce for all ASN.1 type classes. @author Sylvain Daubert

Public Class Methods

constructed() click to toggle source

Give all constructed types @return [Array<Types::Constructed>]

# File lib/rasn1/types.rb, line 16
def self.constructed
  @constructed ||= self.constants.map { |c| Types.const_get(c) }
                       .select { |klass| klass < Constructed }
end
decode_identifier_octets(der) click to toggle source

@private Decode a DER string to extract identifier octets. @param [String] der @return [Array] Return ASN.1 class as Symbol, contructed/primitive as Symbol,

ID and size of identifier octets
# File lib/rasn1/types.rb, line 26
def self.decode_identifier_octets(der)
  first_octet = der[0].unpack1('C')
  asn1_class = Types::Base::CLASSES.key(first_octet & Types::Base::CLASS_MASK)
  pc = (first_octet & Types::Constructed::ASN1_PC).positive? ? :constructed : :primitive
  id = first_octet & Types::Base::MULTI_OCTETS_ID

  size = if id == Types::Base::MULTI_OCTETS_ID
           id = 0
           1.upto(der.size - 1) do |i|
             octet = der[i].unpack1('C')
             id = (id << 7) | (octet & 0x7f)
             break i + 1 if (octet & 0x80).zero?
           end
         else
           1
         end

  [asn1_class, pc, id, size]
end
id2type(der) click to toggle source

Give ASN.1 type from a DER string. If ID is unknown, return a {Types::Base} object. @param [String] der @return [Types::Base] @raise [ASN1Error] tag is out of range

# File lib/rasn1/types.rb, line 51
def self.id2type(der)
  # Define a cache for well-known ASN.1 types
  unless defined? @id2types
    constructed = self.constructed - [Types::SequenceOf, Types::SetOf]
    primitives = self.primitives - [Types::Enumerated]
    ary = (primitives + constructed).map do |type|
      next unless type.const_defined? :ID

      [type::ID, type]
    end
    @id2types = Hash[ary]
    @id2types.default = Types::Base
    @id2types.freeze
  end

  asn1class, pc, id, = self.decode_identifier_octets(der)
  # cache_id: check versus class and 5 LSB bits
  cache_id = der.unpack1('C') & 0xdf
  klass = cache_id < Types::Base::MULTI_OCTETS_ID ? @id2types[id] : Types::Base
  is_constructed = (pc == :constructed)
  options = { class: asn1class, constructed: is_constructed }
  options[:tag_value] = id if klass == Types::Base
  klass.new(options)
end
primitives() click to toggle source

Give all primitive types @return [Array<Types::Primitive>]

# File lib/rasn1/types.rb, line 9
def self.primitives
  @primitives ||= self.constants.map { |c| Types.const_get(c) }
                      .select { |klass| klass < Primitive }
end