diff options
Diffstat (limited to 'lib/asn1kit/berstring.rb')
-rw-r--r-- | lib/asn1kit/berstring.rb | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/asn1kit/berstring.rb b/lib/asn1kit/berstring.rb new file mode 100644 index 0000000..23b9e93 --- /dev/null +++ b/lib/asn1kit/berstring.rb @@ -0,0 +1,70 @@ +module ASN1Kit + module BERString + TAG_CLASS_MAP = { + UNIVERSAL: 0x00, + APPLICATION: 0x40, + CONTEXT_SPECIFIC: 0x80, + PRIVATE: 0xC0 + } + + refine(String) do + def put_object(tc, tn, len, encoding) + force_encoding("BINARY") + constructed = encoding == :constructed + if tn < 0x1f + self << (TAG_CLASS_MAP[tc] | (constructed ? 0x20 : 0x00) | tn) + else + self << (TAG_CLASS_MAP[tc] | (constructed ? 0x20 : 0x00) | 0x1f) + self << [tn].pack("w") + end + if len && len < 0x80 + self << len + elsif !len + self << 0x80 + else + d = len.digits(256) + self << (0x80 | d.size) + self << d.reverse.pack("C") + end + end + + def put_eoc + force_encoding("BINARY") + self << 0x00 + self << 0x00 + end + + # Returns an array: [tag_class, is_constructed, tag_number, hlen, len] + # where + # tag_class:: one of :UNIVERSAL, :APPLICATION, :CONTEXT_SPECIFIC, :PRIVATE + # is_constructed:: true of false + # tag_number:: an Integer + # hlen:: header octets length + # len:: content octets length + def get_object(offset = 0) + h = getbyte(offset) or + raise RangeError, "end of string reached" + hlen = 1 + tag_class = [:UNIVERSAL, :APPLICATION, :CONTEXT_SPECIFIC, :PRIVATE][h >> 6] + constructed = h & 0x20 == 0x20 + tag_number = h & 0x1f + if tag_number == 0x1f + tag_number = unpack("@#{offset + hlen} w")[0] or + raise RangeError, "end of string reached" + hlen += (tag_number.bit_length / 8r).ceil + end + len = getbyte(offset + hlen) or + raise RangeError, "end of string reached" + hlen += 1 + if len > 0x80 + blen = len - 0x80 + d = unpack("@#{offset + hlen} C#{blen}") + d[-1] or raise RangeError, "end of string reached" + len = d.inject(0) { |sum, i| (sum << 8) + i } + hlen += blen + end + [tag_class, tag_number, constructed, hlen, len] + end + end + end +end |