Module: PQCrypto::PKCS8::DER

Defined in:
lib/pq_crypto/pkcs8/der.rb

Class Method Summary collapse

Class Method Details

.decode_length(der, offset) ⇒ Object

Raises:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/pq_crypto/pkcs8/der.rb', line 41

def decode_length(der, offset)
  first = der.getbyte(offset)
  raise SerializationError, "PKCS#8 DER length is missing" if first.nil?

  return [first, 1] if first < 0x80

  length_octets = first & 0x7f
  raise SerializationError, "PKCS#8 DER indefinite length is not allowed" if length_octets.zero?
  raise SerializationError, "PKCS#8 DER length is too large" if length_octets > 4
  if offset + 1 + length_octets > der.bytesize
    raise SerializationError, "PKCS#8 DER length exceeds available data"
  end

  length = 0
  length_octets.times do |i|
    byte = der.getbyte(offset + 1 + i)
    length = (length << 8) | byte
  end

  if length < 0x80 || (length_octets > 1 && der.getbyte(offset + 1).zero?)
    raise SerializationError, "PKCS#8 DER length is not minimally encoded"
  end

  [length, 1 + length_octets]
end

.decode_tlv(der, offset, expected_tag:, label:) ⇒ Object

Raises:



12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/pq_crypto/pkcs8/der.rb', line 12

def decode_tlv(der, offset, expected_tag:, label:)
  tag = der.getbyte(offset)
  raise SerializationError, "PKCS#8 #{label} is missing" if tag.nil?
  unless tag == expected_tag
    raise SerializationError, "PKCS#8 #{label} has unexpected tag: 0x#{tag.to_s(16).rjust(2, '0')}"
  end

  length, length_bytes = decode_length(der, offset + 1)
  value_offset = offset + 1 + length_bytes
  value_end = value_offset + length
  raise SerializationError, "PKCS#8 #{label} length exceeds available data" if value_end > der.bytesize

  [tag, der.byteslice(value_offset, length).b, value_end]
end

.encode_length(length) ⇒ Object

Raises:



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/pq_crypto/pkcs8/der.rb', line 27

def encode_length(length)
  raise SerializationError, "Invalid DER length" if length.negative?
  return length.chr.b if length < 0x80

  encoded = []
  remaining = length
  until remaining.zero?
    encoded.unshift(remaining & 0xff)
    remaining >>= 8
  end

  (0x80 | encoded.length).chr.b + encoded.pack("C*").b
end

.encode_tlv(tag, value) ⇒ Object



8
9
10
# File 'lib/pq_crypto/pkcs8/der.rb', line 8

def encode_tlv(tag, value)
  tag.chr.b + encode_length(value.bytesize) + value
end