rnp 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
-