rnp 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +5 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.adoc +3 -182
  5. data/lib/rnp.rb +12 -3
  6. data/lib/rnp/error.rb +40 -0
  7. data/lib/rnp/ffi/librnp.rb +306 -0
  8. data/lib/rnp/input.rb +99 -0
  9. data/lib/rnp/key.rb +275 -0
  10. data/lib/rnp/misc.rb +71 -0
  11. data/lib/rnp/op/encrypt.rb +181 -0
  12. data/lib/rnp/op/sign.rb +139 -0
  13. data/lib/rnp/op/verify.rb +147 -0
  14. data/lib/rnp/output.rb +121 -0
  15. data/lib/rnp/rnp.rb +595 -0
  16. data/lib/rnp/utils.rb +44 -0
  17. data/lib/rnp/version.rb +8 -3
  18. metadata +124 -50
  19. data/.gitignore +0 -12
  20. data/.rspec +0 -2
  21. data/.travis.yml +0 -5
  22. data/CODE_OF_CONDUCT.md +0 -74
  23. data/Gemfile +0 -4
  24. data/Rakefile +0 -6
  25. data/Use_Cases.adoc +0 -119
  26. data/bin/console +0 -14
  27. data/bin/setup +0 -8
  28. data/example-usage.rb +0 -766
  29. data/examples/highlevel/decrypt_mem.rb +0 -44
  30. data/examples/highlevel/encrypt_mem.rb +0 -46
  31. data/examples/lowlevel/decrypt_file.rb +0 -76
  32. data/examples/lowlevel/decrypt_mem.rb +0 -80
  33. data/examples/lowlevel/encrypt_file.rb +0 -68
  34. data/examples/lowlevel/encrypt_mem.rb +0 -75
  35. data/examples/lowlevel/load_pubkey.rb +0 -118
  36. data/examples/lowlevel/print_keyring_file.rb +0 -68
  37. data/examples/lowlevel/print_keyring_mem.rb +0 -96
  38. data/examples/lowlevel/sign_file.rb +0 -104
  39. data/examples/lowlevel/sign_mem.rb +0 -96
  40. data/examples/lowlevel/verify_file.rb +0 -55
  41. data/examples/lowlevel/verify_mem.rb +0 -61
  42. data/lib/rnp/highlevel.rb +0 -5
  43. data/lib/rnp/highlevel/constants.rb +0 -96
  44. data/lib/rnp/highlevel/keyring.rb +0 -259
  45. data/lib/rnp/highlevel/publickey.rb +0 -150
  46. data/lib/rnp/highlevel/secretkey.rb +0 -318
  47. data/lib/rnp/highlevel/utils.rb +0 -119
  48. data/lib/rnp/lowlevel.rb +0 -6
  49. data/lib/rnp/lowlevel/constants.rb +0 -11
  50. data/lib/rnp/lowlevel/dynarray.rb +0 -129
  51. data/lib/rnp/lowlevel/enums.rb +0 -243
  52. data/lib/rnp/lowlevel/libc.rb +0 -28
  53. data/lib/rnp/lowlevel/libopenssl.rb +0 -15
  54. data/lib/rnp/lowlevel/librnp.rb +0 -213
  55. data/lib/rnp/lowlevel/structs.rb +0 -541
  56. data/lib/rnp/lowlevel/utils.rb +0 -25
  57. data/rnp.gemspec +0 -35
  58. data/rnp/lib/rnp.rb +0 -5
  59. data/rnp/spec/rnp_spec.rb +0 -11
@@ -1,5 +0,0 @@
1
- require_relative 'highlevel/constants'
2
- require_relative 'highlevel/publickey'
3
- require_relative 'highlevel/secretkey'
4
- require_relative 'highlevel/keyring'
5
-
@@ -1,96 +0,0 @@
1
- require 'rubygems'
2
-
3
- module RNP
4
-
5
- class PublicKeyAlgorithm
6
- NONE = 0
7
- RSA = 1
8
- RSA_ENCRYPT_ONLY = 2
9
- RSA_SIGN_ONLY = 3
10
- ELGAMAL = 16
11
- DSA = 17
12
- ECDH = 18
13
- ECDSA = 19
14
- FORMERLY_ELGAMAL = 20
15
-
16
- def self.from_native(alg)
17
- raise if alg.class != Symbol
18
- LibRNP::PGP_PUBKEY_ALG_T[alg]
19
- end
20
-
21
- def self.to_native(alg)
22
- # avoid a warning on newer versions of ruby
23
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.4.0')
24
- raise if alg.class != Integer
25
- else
26
- raise if alg.class != Fixnum
27
- end
28
- LibRNP::PGP_PUBKEY_ALG_T[alg]
29
- end
30
-
31
- end
32
-
33
- class HashAlgorithm
34
- MD5 = 1
35
- SHA1 = 2
36
- RIPEMD = 3
37
- SHA256 = 8
38
- SHA384 = 9
39
- SHA512 = 10
40
- SHA224 = 11
41
-
42
- # see pgp_str_to_hash_alg
43
- STRING_MAPPING = {
44
- MD5 => 'md5',
45
- SHA1 => 'sha1',
46
- SHA256 => 'sha256',
47
- SHA384 => 'sha384',
48
- SHA512 => 'sha512'
49
- }
50
-
51
- def self.to_s(alg)
52
- STRING_MAPPING[alg]
53
- end
54
-
55
- end
56
-
57
- class SymmetricKeyAlgorithm
58
- PLAINTEXT = 0
59
- IDEA = 1
60
- TRIPLEDES = 2
61
- CAST5 = 3
62
- BLOWFISH = 4
63
- AES128 = 7
64
- AES192 = 8
65
- AES256 = 9
66
- TWOFISH256 = 10
67
-
68
- # see pgp_str_to_cipher
69
- STRING_MAPPING = {
70
- IDEA => 'idea',
71
- TRIPLEDES => 'tripledes',
72
- CAST5 => 'cast5',
73
- AES128 => 'aes128',
74
- AES256 => 'aes256'
75
- }
76
-
77
- def self.to_s(alg)
78
- STRING_MAPPING[alg]
79
- end
80
-
81
- end
82
-
83
- class StringToKeyUsage
84
- NONE = 0
85
- ENCRYPTED_AND_HASHED = 254
86
- ENCRYPTED = 255
87
- end
88
-
89
- class StringToKeySpecifier
90
- SIMPLE = 0
91
- SALTED = 1
92
- ITERATED_AND_SALTED = 3
93
- end
94
-
95
- end
96
-
@@ -1,259 +0,0 @@
1
- require 'English'
2
- require 'forwardable'
3
-
4
- module RNP
5
-
6
- class Keyring
7
- extend Forwardable
8
- delegate [:size, :each, :select, :[], :push, :clear] => :@keys
9
-
10
- attr_reader :keys
11
-
12
- def initialize
13
- @keys = []
14
- end
15
-
16
- def self.load(data, armored=true, &passphrase_provider)
17
- kr = Keyring.new
18
- kr.add(data, armored, &passphrase_provider)
19
- kr
20
- end
21
-
22
- def add(data, armored=true, &passphrase_provider)
23
- keys = RNP::load_keys(data, armored, &passphrase_provider)
24
- @keys.push(*keys)
25
- keys.size
26
- end
27
-
28
- def verify(data, armored=true)
29
- RNP::verify(@keys, data, armored)
30
- end
31
-
32
- def export(key, armored=true)
33
- raise if key.parent
34
- is_public = key.is_a?(PublicKey)
35
- if is_public
36
- seckey = secret_keys.find {|sk| sk.key_id == key.key_id}
37
- else
38
- seckey = key
39
- end
40
- return nil if not seckey
41
- output_ptr = FFI::MemoryPointer.new(:pointer)
42
- mem_ptr = FFI::MemoryPointer.new(:pointer)
43
- output = nil
44
- mem = nil
45
- decrypted_seckey = nil
46
- begin
47
- LibRNP::pgp_setup_memory_write(output_ptr, mem_ptr, 4096)
48
- output = LibRNP::PGPOutput.new(output_ptr.read_pointer)
49
- mem = LibRNP::PGPMemory.new(mem_ptr.read_pointer)
50
- native_ptr = LibC::calloc(1, LibRNP::PGPKey.size)
51
- native = LibRNP::PGPKey.new(native_ptr)
52
- native_auto = FFI::AutoPointer.new(native_ptr, LibRNP::PGPKey.method(:release))
53
- key.to_native_key(native)
54
- decrypted_seckey = seckey.decrypted_seckey
55
- return nil if not decrypted_seckey
56
- # this is necessary for signatures
57
- seckey = SecretKey.from_native(decrypted_seckey)
58
- seckey.to_native(native[:key][:seckey])
59
- native[:type] = :PGP_PTAG_CT_SECRET_KEY
60
- if is_public
61
- LibRNP::dynarray_clear(native, 'uid', :string)
62
- key.userids.each {|userid|
63
- LibRNP::pgp_add_selfsigned_userid(native, userid)
64
- }
65
- end
66
- # PGPKeyring is a ManagedStruct
67
- subkeysring_ptr = LibC::calloc(1, LibRNP::PGPKeyring.size)
68
- subkeysring = LibRNP::PGPKeyring.new(subkeysring_ptr)
69
- RNP::keys_to_native_keyring(key.subkeys, subkeysring)
70
- # add a binding signature to each subkey
71
- (0..LibRNP::dynarray_count(subkeysring, 'key') - 1).each {|n|
72
- subkey = LibRNP::dynarray_get_item(subkeysring, 'key', LibRNP::PGPKey, n)
73
- LibRNP::dynarray_clear(subkey, 'packet', LibRNP::PGPSubPacket)
74
- RNP::add_subkey_signature(native, subkey)
75
- }
76
- if is_public
77
- ret = LibRNP::pgp_write_xfer_pubkey(output, native, subkeysring, armored ? 1 : 0)
78
- else
79
- decrypted_key_ptr = LibC::calloc(1, LibRNP::PGPKey.size)
80
- decrypted_key = LibRNP::PGPKey.new(decrypted_key_ptr)
81
- decrypted_key_auto = FFI::AutoPointer.new(decrypted_key_ptr, LibRNP::PGPKey.method(:release))
82
- seckey.to_native_key(decrypted_key)
83
- key.userids.each {|userid|
84
- LibRNP::pgp_add_selfsigned_userid(decrypted_key, userid)
85
- }
86
- decrypted_key[:key][:seckey][:s2k_usage] = :PGP_S2KU_ENCRYPTED_AND_HASHED
87
- decrypted_key[:key][:seckey][:alg] = :PGP_SA_CAST5
88
- decrypted_key[:key][:seckey][:s2k_specifier] = :PGP_S2KS_SALTED
89
- (0..LibRNP::dynarray_count(subkeysring, 'key') - 1).each {|n|
90
- subkey = LibRNP::dynarray_get_item(subkeysring, 'key', LibRNP::PGPKey, n)
91
- subkey[:key][:seckey][:s2k_usage] = :PGP_S2KU_ENCRYPTED_AND_HASHED
92
- subkey[:key][:seckey][:alg] = :PGP_SA_CAST5
93
- subkey[:key][:seckey][:s2k_specifier] = :PGP_S2KS_SALTED
94
- }
95
- ret = LibRNP::pgp_write_xfer_seckey(output, decrypted_key, key.passphrase, key.passphrase.size, subkeysring, armored ? 1 : 0)
96
- end
97
- return nil if ret != 1
98
- data = mem[:buf].read_bytes(mem[:length])
99
- data
100
- ensure
101
- LibRNP::pgp_teardown_memory_write(output, mem) if mem
102
- LibRNP::pgp_seckey_free(decrypted_seckey) if decrypted_seckey
103
- end
104
- end
105
-
106
- def public_keys
107
- self.select {|key|
108
- key.is_a?(PublicKey)
109
- }
110
- end
111
-
112
- def secret_keys
113
- self.select {|key|
114
- key.is_a?(SecretKey)
115
- }
116
- end
117
-
118
- def to_native(native)
119
- keys_to_native_keyring(@keys, native)
120
- end
121
-
122
- end
123
-
124
- PARSE_KEYRING = Proc.new do |state, passphrase_provider, pkt, data|
125
- next :PGP_RELEASE_MEMORY if state[:errors].any?
126
-
127
- begin
128
- lastkey = state[:keys].last
129
- case pkt[:tag]
130
- when :PGP_PTAG_CT_PUBLIC_KEY
131
- key = PublicKey::from_native(pkt[:u][:pubkey])
132
- state[:keys].push(key)
133
- when :PGP_PTAG_CT_PUBLIC_SUBKEY
134
- key = PublicKey::from_native(pkt[:u][:pubkey])
135
- lastkey.add_subkey(key)
136
- state[:keys].push(key)
137
- when :PGP_PTAG_CT_ENCRYPTED_SECRET_KEY
138
- key = SecretKey::from_native(pkt[:u][:seckey], true)
139
- state[:keys].push(key)
140
- when :PGP_PTAG_CT_ENCRYPTED_SECRET_SUBKEY
141
- key = SecretKey::from_native(pkt[:u][:seckey], true)
142
- lastkey.add_subkey(key)
143
- state[:keys].push(key)
144
- when :PGP_PTAG_CT_SECRET_KEY
145
- key = SecretKey::from_native(pkt[:u][:seckey])
146
- if state[:passphrase]
147
- key.passphrase = state[:passphrase]
148
- state[:passphrase] = nil
149
- end
150
- state[:keys].push(key)
151
- when :PGP_PTAG_CT_SECRET_SUBKEY
152
- key = SecretKey::from_native(pkt[:u][:seckey])
153
- lastkey.add_subkey(key)
154
- state[:keys].push(key)
155
- when :PGP_GET_PASSPHRASE
156
- seckey_ptr = pkt[:u][:skey_passphrase][:seckey]
157
- seckey = LibRNP::PGPSecKey.new(seckey_ptr)
158
- key = SecretKey::from_native(seckey)
159
- passphrase = passphrase_provider.call(key)
160
- if passphrase and passphrase != ''
161
- passphrase_mem = LibC::calloc(1, passphrase.bytesize + 1)
162
- passphrase_mem.write_bytes(passphrase)
163
- pkt[:u][:skey_passphrase][:passphrase].write_pointer(passphrase_mem)
164
- state[:passphrase] = passphrase
165
- next :PGP_KEEP_MEMORY
166
- end
167
- when :PGP_PARSER_PACKET_END
168
- if lastkey.is_a? RNP::SecretKey
169
- raw_packet = pkt[:u][:packet]
170
- bytes = raw_packet[:raw].read_bytes(raw_packet[:length])
171
- lastkey.raw_subpackets.push(bytes)
172
- end
173
- when :PGP_PTAG_CT_USER_ID
174
- lastkey.userids.push(pkt[:u][:userid].force_encoding('utf-8'))
175
- when :PGP_PTAG_SS_KEY_EXPIRY
176
- lastkey.expiration_time = lastkey.creation_time + pkt[:u][:ss_time]
177
- else
178
- # For debugging
179
- #puts "Unhandled tag: #{pkt[:tag]}"
180
- end # case
181
- rescue
182
- state[:errors].push($ERROR_INFO)
183
- end
184
- next :PGP_RELEASE_MEMORY
185
- end
186
-
187
- DEFAULT_PASSPHRASE_PROVIDER = Proc.new do |seckey|
188
- nil
189
- end
190
-
191
- def self.load_keys(data, armored=true, &passphrase_provider)
192
- # Just for readability
193
- print_errors = 0
194
- stream_mem = LibC::calloc(1, LibRNP::PGPStream.size)
195
- # This will free the above memory (PGPStream is a ManagedStruct)
196
- stream = LibRNP::PGPStream.new(stream_mem)
197
- stream[:readinfo][:accumulate] = 1
198
- LibRNP::pgp_parse_options(stream, :PGP_PTAG_SS_ALL, :PGP_PARSE_PARSED)
199
-
200
- # This memory will be GC'd
201
- mem = FFI::MemoryPointer.new(:uint8, data.bytesize)
202
- mem.write_bytes(data)
203
-
204
- LibRNP::pgp_reader_set_memory(stream, mem, mem.size)
205
- state = {keys: [], errors: []}
206
- provider = block_given? ? passphrase_provider : DEFAULT_PASSPHRASE_PROVIDER
207
- callback = RNP::PARSE_KEYRING.curry[state][provider]
208
- LibRNP::pgp_set_callback(stream, callback, nil)
209
- LibRNP::pgp_reader_push_dearmour(stream) if armored
210
- if LibRNP::pgp_parse(stream, print_errors) != 1
211
- state[:errors].push('pgp_parse failed')
212
- end
213
- LibRNP::pgp_reader_pop_dearmour(stream) if armored
214
-
215
- errors = stream_errors(stream)
216
- state[:errors].push(errors) if errors.any?
217
-
218
- raise state[:errors].join("\n") if state[:errors].any?
219
- state[:keys]
220
- end
221
-
222
- def self.keys_to_native_keyring(keys, native)
223
- raise if not native[:keys].null?
224
-
225
- for key in keys
226
- native_key = LibRNP::PGPKey.new
227
- key.to_native_key(native_key)
228
- LibRNP::dynarray_append_item(native, 'key', LibRNP::PGPKey, native_key)
229
- end
230
- end
231
-
232
- def self.verify(keys, data, armored=true)
233
- native_keyring_ptr = LibC::calloc(1, LibRNP::PGPKeyring.size)
234
- native_keyring = LibRNP::PGPKeyring.new(native_keyring_ptr)
235
- RNP::keys_to_native_keyring(keys, native_keyring)
236
-
237
- pgpio = LibRNP::PGPIO.new
238
- pgpio[:outs] = LibC::fdopen($stdout.to_i, 'w')
239
- pgpio[:errs] = LibC::fdopen($stderr.to_i, 'w')
240
- pgpio[:res] = pgpio[:errs]
241
-
242
- data_buf = FFI::MemoryPointer.new(:uint8, data.bytesize)
243
- data_buf.write_bytes(data)
244
-
245
- # pgp_validate_mem frees this
246
- mem_ptr = LibC::calloc(1, LibRNP::PGPMemory.size)
247
- mem = LibRNP::PGPMemory.new(mem_ptr)
248
- LibRNP::pgp_memory_add(mem, data_buf, data_buf.size)
249
-
250
- # ManagedStruct, this frees itself
251
- result_ptr = LibC::calloc(1, LibRNP::PGPValidation.size)
252
- result = LibRNP::PGPValidation.new(result_ptr)
253
-
254
- ret = LibRNP::pgp_validate_mem(pgpio, result, mem, nil, armored ? 1 : 0, native_keyring)
255
- ret == 1
256
- end
257
-
258
- end # module RNP
259
-
@@ -1,150 +0,0 @@
1
- module RNP
2
-
3
- require_relative 'utils'
4
-
5
- class PublicKey
6
- attr_accessor :version,
7
- :creation_time,
8
- :expiration_time,
9
- :public_key_algorithm,
10
- :mpi,
11
- :userids,
12
- :parent,
13
- :subkeys
14
-
15
- def initialize
16
- @version = nil
17
- @creation_time = nil
18
- @expiration_time = 0
19
- @public_key_algorithm = nil
20
- @mpi = {}
21
- @userids = []
22
- @parent = nil
23
- @subkeys = []
24
- end
25
-
26
- def fingerprint
27
- fp = LibRNP::PGPFingerprint.new
28
- native_pubkey_ptr = LibC::calloc(1, LibRNP::PGPPubKey.size)
29
- native_pubkey = LibRNP::PGPPubKey.new(native_pubkey_ptr)
30
- native_pubkey_auto = FFI::AutoPointer.new(native_pubkey_ptr, LibRNP::PGPPubKey.method(:release))
31
- to_native(native_pubkey)
32
- hash = @version == 3 ? :PGP_HASH_MD5 : :PGP_HASH_SHA1
33
- ret = LibRNP::pgp_fingerprint(fp, native_pubkey, hash)
34
- raise 'pgp_fingerprint failed' if ret != 1
35
- fp[:fingerprint].to_s[0, fp[:length]]
36
- end
37
-
38
- def fingerprint_hex
39
- fingerprint.bytes.collect {|byte| '%02X' % byte}.join
40
- end
41
-
42
- def key_id
43
- keyid_ptr = FFI::MemoryPointer.new(:uint8, LibRNP::PGP_KEY_ID_SIZE)
44
- native_pubkey = LibRNP::PGPPubKey.new
45
- to_native(native_pubkey)
46
- ret = LibRNP::pgp_keyid(keyid_ptr, LibRNP::PGP_KEY_ID_SIZE, native_pubkey, :PGP_HASH_SHA1)
47
- raise 'pgp_keyid failed' if ret != 1
48
- keyid_ptr.read_bytes(LibRNP::PGP_KEY_ID_SIZE)
49
- end
50
-
51
- def key_id_hex
52
- key_id.bytes.collect {|byte| '%02X' % byte}.join
53
- end
54
-
55
- def key_length
56
- case @public_key_algorithm
57
- when PublicKeyAlgorithm::RSA,
58
- PublicKeyAlgorithm::RSA_ENCRYPT_ONLY,
59
- PublicKeyAlgorithm::RSA_SIGN_ONLY
60
- return RNP::bignum_byte_count(@mpi[:n]) * 8
61
- when PublicKeyAlgorithm::DSA
62
- case RNP::bignum_byte_count(@mpi[:q])
63
- when 20
64
- 1024
65
- when 28
66
- 2048
67
- when 32
68
- 3072
69
- end
70
- when PublicKeyAlgorithm::ELGAMAL
71
- RNP::bignum_byte_count(@mpi[:y]) * 8
72
- end
73
- 0
74
- end
75
-
76
- def encrypt(data, armored=true, sk_algorithm=SymmetricKeyAlgorithm::CAST5)
77
- cipher = SymmetricKeyAlgorithm::to_s(sk_algorithm)
78
- memory = nil
79
-
80
- begin
81
- pubkey_ptr = LibC::calloc(1, LibRNP::PGPKey.size)
82
- pubkey = LibRNP::PGPKey.new(pubkey_ptr)
83
- pubkey_auto = FFI::AutoPointer.new(pubkey_ptr, LibRNP::PGPKey.method(:release))
84
-
85
- to_native_key(pubkey)
86
- data_buf = FFI::MemoryPointer.new(:uint8, data.bytesize)
87
- data_buf.write_bytes(data)
88
- pgpio = LibRNP::PGPIO.new
89
- pgpio[:outs] = LibC::fdopen($stdout.to_i, 'w')
90
- pgpio[:errs] = LibC::fdopen($stderr.to_i, 'w')
91
- pgpio[:res] = pgpio[:errs]
92
- memory_ptr = LibRNP::pgp_encrypt_buf(pgpio, data_buf, data_buf.size, pubkey, armored ? 1 : 0, cipher)
93
- return nil if memory_ptr.null?
94
- memory = LibRNP::PGPMemory.new(memory_ptr)
95
- memory[:buf].read_bytes(memory[:length])
96
- ensure
97
- LibRNP::pgp_memory_free(memory) if memory
98
- end
99
- end
100
-
101
- def verify(data, armored=true)
102
- RNP::verify([self], data, armored)
103
- end
104
-
105
- def add_subkey(subkey)
106
- raise if subkey.subkeys.any?
107
- subkey.parent = self
108
- subkey.userids = @userids
109
- @subkeys.push(subkey)
110
- end
111
-
112
- def self.from_native(native)
113
- pubkey = PublicKey.new
114
- pubkey.version = LibRNP::enum_value(native[:version])
115
- pubkey.creation_time = Time.at(native[:birthtime])
116
- if pubkey.version == 3
117
- pubkey.expiration_time = Time.at(native[:birthtime]) + (native[:days_valid] * 86400)
118
- end
119
- pubkey.public_key_algorithm = PublicKeyAlgorithm::from_native(native[:alg])
120
- pubkey.mpi = RNP::mpis_from_native(native[:alg], native)
121
- pubkey
122
- end
123
-
124
- def to_native(native)
125
- native[:version] = @version
126
- native[:birthtime] = @creation_time.to_i
127
- if @version == 3 and @expiration_time
128
- native[:days_valid] = ((@expiration_time.to_i - @creation_time.to_i) / 86400).to_i
129
- else
130
- native[:duration] = (@expiration_time.to_i - @creation_time.to_i).to_i
131
- end
132
- native[:alg] = @public_key_algorithm
133
- RNP::mpis_to_native(native[:alg], @mpi, native)
134
- end
135
-
136
- def to_native_key(native_key)
137
- native_key[:type] = :PGP_PTAG_CT_PUBLIC_KEY
138
- native_key[:sigid] = key_id
139
- to_native(native_key[:key][:pubkey])
140
- if not @parent
141
- @userids.each {|userid|
142
- LibRNP::dynarray_append_item(native_key, 'uid', :string, userid)
143
- }
144
- end
145
- end
146
-
147
- end
148
-
149
- end # module RNP
150
-