aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1kit/berstring.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1kit/berstring.rb')
-rw-r--r--lib/asn1kit/berstring.rb70
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