Class: CyberplatPKI::Key

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

Defined Under Namespace

Modules: Helpers

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeKey

Returns a new instance of Key.



64
65
66
67
68
69
70
# File 'lib/cyberplat_pki/key.rb', line 64

def initialize
  @serial = nil
  @name = nil
  @signature = nil
  @ca_key = nil
  @packets = nil
end

Instance Attribute Details

#ca_keyObject

Returns the value of attribute ca_key.



31
32
33
# File 'lib/cyberplat_pki/key.rb', line 31

def ca_key
  @ca_key
end

#nameObject

Returns the value of attribute name.



31
32
33
# File 'lib/cyberplat_pki/key.rb', line 31

def name
  @name
end

#packetsObject

Returns the value of attribute packets.



31
32
33
# File 'lib/cyberplat_pki/key.rb', line 31

def packets
  @packets
end

#serialObject

Returns the value of attribute serial.



31
32
33
# File 'lib/cyberplat_pki/key.rb', line 31

def serial
  @serial
end

#signatureObject

Returns the value of attribute signature.



31
32
33
# File 'lib/cyberplat_pki/key.rb', line 31

def signature
  @signature
end

Class Method Details

.new_private(source, password = nil) ⇒ Object



33
34
35
36
37
38
39
40
# File 'lib/cyberplat_pki/key.rb', line 33

def self.new_private(source, password = nil)
  documents = Document.load source

  key, document = Helpers.key_from_document_set documents, :NM, 0, password
  key.ca_key = key

  key
end

.new_public(source, serial, ca_key = nil) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/cyberplat_pki/key.rb', line 42

def self.new_public(source, serial, ca_key = nil)
  documents = Document.load source

  key, document = Helpers.key_from_document_set documents, :NS, serial
  if ca_key.nil?
    if document.subject == document.ca
      key.ca_key = key
    else
      key.ca_key, ca_document = Helpers.key_from_document_set documents, :NS, document.ca.key_serial
      key.ca_key.ca_key = key.ca_key

      key.ca_key.validate
    end
  else
    key.ca_key = ca_key
  end

  key.validate

  key
end

Instance Method Details

#sign(data) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/cyberplat_pki/key.rb', line 72

def sign(data)
  signature = SignaturePacket.new

  signature. = [
    0x01,         # Signature type
    serial,       # Signing key serial number
    Time.now.to_i # Timestamp
  ].pack("CNN")

  key_packet = Helpers.find_record packets, KeyPacket

  digest = OpenSSL::Digest::MD5.new
  signature.signature = key_packet.key.sign digest, data + signature.

  # Re-hash to get 'first word of digest'
  digest.reset
  digest.update data
  digest.update signature.
  signature.hash_msw = digest.digest[0..1]

  trust = TrustPacket.new
  trust.trust = 0xC7.chr

  signature_block = Packet.save([ signature, trust ])

  doc = Document.new
  doc.engine      = 1
  doc.type        = :SM
  doc.subject     = KeyId.new @name, @serial
  doc.ca          = KeyId.new '', 0
  doc.data_length = data.length
  doc.body        = data
  doc.signature   = Document.encode64 signature_block

  text = Document.save [ doc ]

  text
end

#validateObject



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/cyberplat_pki/key.rb', line 126

def validate
  signature_packet = Helpers.find_record signature,      SignaturePacket
  key_packet       = Helpers.find_record packets,        KeyPacket
  user_id_packet   = Helpers.find_record packets,        UserIdPacket
  ca_key_packet    = Helpers.find_record ca_key.packets, KeyPacket

  io = StringIO.open ''.encode('BINARY'), 'wb'
  io.extend PacketIORoutines

  io.seek 3
  key_packet.save io, nil

  data_length = io.pos - 3
  io.rewind
  io.write [ 0x99, data_length ].pack "Cn"
  io.seek 0, IO::SEEK_END

  io.write user_id_packet.user_id
  io.write signature_packet.

  digest = OpenSSL::Digest::MD5.new
  signature = signature_packet.signature.rjust ca_key_packet.key.n.num_bytes, 0.chr
  valid = ca_key_packet.key.verify digest, signature, io.string

  raise "CyberplatPKI: CRYPT_ERR_INVALID_KEY (key signature verification failed)" unless valid
end

#verify(data_with_signature) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/cyberplat_pki/key.rb', line 111

def verify(data_with_signature)
  documents = Document.load data_with_signature

  raise "CyberplatPKI: CRYPT_ERR_INVALID_FORMAT (expected one document of type SM)" if documents.length != 1 || documents[0].type != :SM

  document, = *documents

  signature_packet, = Packet.load Document.decode64(document.signature)
  key_packet        = Helpers.find_record packets, KeyPacket

  digest = OpenSSL::Digest::MD5.new
  signature = signature_packet.signature.ljust key_packet.key.n.num_bytes, 0.chr
  key_packet.key.verify digest, signature, document.body + signature_packet.
end