Class: PqcAsn1::DER::Cursor

Inherits:
Object
  • Object
show all
Defined in:
lib/pqc_asn1.rb

Overview

Zero-copy DER reader for callers that need fine-grained traversal beyond parse_spki / parse_pkcs8.

Advanced API — most callers should use the high-level methods (parse_spki, parse_pkcs8, parse_encrypted_pkcs8) instead. Use Cursor only when you need to navigate a custom DER structure that the built-in parsers do not cover.

A Cursor wraps a binary String and provides sequential read operations that advance an internal position without copying data. #read_sequence returns a new Cursor scoped to the SEQUENCE content, sharing the same source — still zero-copy.

All read_* methods return frozen ASCII-8BIT Strings. The Cursor holds a strong reference to the source String, preventing GC while any sub-cursor is alive.

Defined by the C extension (ext/pqc_asn1/cursor.c).

Examples:

Parsing a custom DER structure

cursor = PqcAsn1::DER::Cursor.new(der_bytes)
seq    = cursor.read_sequence
oid    = seq.read_oid          # tag 0x06 content bytes
key    = seq.read_bit_string   # tag 0x03 content bytes
assert seq.eof?

Reading optional fields

seq = PqcAsn1::DER::Cursor.new(der).read_sequence
version = seq.read_optional(0x02)  # nil if not present
algo    = seq.read_sequence

Forwarding an opaque TLV

raw_tlv = cursor.read_raw(0x30)  # full tag+length+value bytes

Instance Method Summary collapse

Constructor Details

#initialize(data, pos = 0) ⇒ Cursor

Create a new Cursor over DER-encoded data.

Parameters:

  • data (String) —

    binary DER bytes

  • pos (Integer) (defaults to: 0) —

    starting byte offset (default 0)



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

Instance Method Details

#data ⇒ String

Return the full backing data of this cursor (or the relevant substring for a sub-cursor). Frozen ASCII-8BIT String.

Returns:

  • (String)


241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#eof? ⇒ Boolean

Returns true if all bytes have been consumed.

Returns:

  • (Boolean) —

    true if all bytes have been consumed



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#peek_tag ⇒ Integer?

Return the tag byte at the current position without advancing.

Returns:

  • (Integer, nil) —

    nil if at EOF



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#pos ⇒ Integer

Returns current byte offset within the source.

Returns:

  • (Integer) —

    current byte offset within the source



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read(expected_tag) ⇒ String

Read the content bytes of the next TLV with the given tag. Advances the cursor past the entire TLV.

Parameters:

  • expected_tag (Integer) —

    DER tag byte (e.g. 0x02, 0x04, 0x06)

Returns:

  • (String) —

    frozen binary content bytes (no tag/length)

Raises:



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_bit_string ⇒ String

Shorthand for read(0x03).

Returns:

  • (String) —

    frozen binary BIT STRING content bytes



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_integer ⇒ String

Shorthand for read(0x02).

Returns:

  • (String) —

    frozen binary INTEGER content bytes



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_octet_string ⇒ String

Shorthand for read(0x04).

Returns:

  • (String) —

    frozen binary OCTET STRING content bytes



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_oid ⇒ String

Shorthand for read(0x06).

Returns:

  • (String) —

    frozen binary OID content bytes



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_optional(expected_tag) ⇒ String?

Like #read but returns nil (without advancing) if at EOF or the next tag does not match.

Parameters:

  • expected_tag (Integer) —

    DER tag byte

Returns:

  • (String, nil)


241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_raw(expected_tag) ⇒ String

Read the full TLV bytes (tag + length + value) at the current position. Useful for forwarding an opaque field without interpreting it.

Parameters:

  • expected_tag (Integer) —

    DER tag byte

Returns:

  • (String) —

    frozen binary TLV bytes

Raises:



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_raw_optional(expected_tag) ⇒ String?

Like #read_raw but returns nil if at EOF or tag mismatch.

Parameters:

  • expected_tag (Integer) —

    DER tag byte

Returns:

  • (String, nil)


241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#read_sequence ⇒ Cursor

Read a SEQUENCE (tag 0x30) and return a new Cursor scoped to its content. The sub-cursor shares the same source String (zero-copy).

Returns:

  • (Cursor) —

    new cursor over the SEQUENCE body

Raises:



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#remaining ⇒ Integer

Returns number of unconsumed bytes.

Returns:

  • (Integer) —

    number of unconsumed bytes



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#skip(expected_tag) ⇒ self

Skip the next TLV with the given tag. Returns self for chaining.

Parameters:

  • expected_tag (Integer) —

    DER tag byte

Returns:

  • (self)

Raises:



241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end

#skip_optional(expected_tag) ⇒ self?

Like #skip but returns nil if at EOF or tag mismatch.

Parameters:

  • expected_tag (Integer) —

    DER tag byte

Returns:

  • (self, nil)


241
# File 'lib/pqc_asn1.rb', line 241

class Cursor; end