rnp 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +4 -1
- data/README.adoc +8 -5
- data/lib/rnp/ffi/librnp.rb +161 -36
- data/lib/rnp/input.rb +30 -10
- data/lib/rnp/key.rb +217 -1
- data/lib/rnp/misc.rb +153 -4
- data/lib/rnp/op/encrypt.rb +26 -22
- data/lib/rnp/op/generate.rb +211 -0
- data/lib/rnp/op/sign.rb +25 -25
- data/lib/rnp/output.rb +14 -0
- data/lib/rnp/rnp.rb +170 -4
- data/lib/rnp/signature.rb +106 -0
- data/lib/rnp/userid.rb +77 -0
- data/lib/rnp/version.rb +2 -3
- data/lib/rnp.rb +3 -1
- metadata +29 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebe16f6b1b161add02098e6bdb70f5401026a0cb31c695c44943d3432b0a1e85
|
4
|
+
data.tar.gz: 10a352991a433807dcd8484931bfc3d6745c86202d23d22b1cc8aa09dd9e848a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5bace27a94afc5fa1c39e25e4c52f020ff3256279f420bf9f0e56010799e10200202afaaebb4fec054e7c7f327e09eac0a10212c08ef4acf0c0251c589873db
|
7
|
+
data.tar.gz: 9cbdb7ec9bc7f6db9ee0ad237fc66b37aae56712aff023cee2c508b502ccec86027867e39dd8e6b134160a94178c56b0e244f9cfdfbae67434c7f075b15ad5cd
|
data/CHANGELOG.adoc
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
== Changelog
|
2
2
|
|
3
|
+
=== 1.0.5 [20-03-2023]
|
4
|
+
* Rub GHA tests for Ruby 2.7, 3.0, 3.1, 3.2, head
|
5
|
+
and different rnp versions
|
6
|
+
|
3
7
|
=== 1.0.4 [09-16-2018]
|
4
8
|
* Add support for rnp 0.11.0+. Tests will now only pass
|
5
9
|
with this version.
|
@@ -17,4 +21,3 @@
|
|
17
21
|
|
18
22
|
=== 1.0.0 [05-01-2018]
|
19
23
|
* Completely rewritten for RNP's new FFI.
|
20
|
-
|
data/README.adoc
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
= Ruby RNP bindings
|
2
2
|
|
3
|
-
image:https://
|
4
|
-
image:https://codecov.io/github/
|
3
|
+
image:https://github.com/rnpgp/ruby-rnp/actions/workflows/tests.yml/badge.svg["Build Status", link="https://github.com/rnpgp/ruby-rnp/actions/workflows/tests.yml"]
|
4
|
+
image:https://codecov.io/github/rnpgp/ruby-rnp/coverage.svg["Code Coverage", link="https://codecov.io/github/rnpgp/ruby-rnp?branch=master"]
|
5
5
|
|
6
6
|
The `rnp` gem provides Ruby bindings to the
|
7
|
-
https://github.com/
|
7
|
+
https://github.com/rnpgp/rnp[librnp OpenPGP library].
|
8
8
|
|
9
|
-
Documentation is available on https://www.rubydoc.info/github/
|
9
|
+
Documentation is available on https://www.rubydoc.info/github/rnpgp/ruby-rnp/master/[RubyDoc].
|
10
|
+
|
11
|
+
== Requirements
|
12
|
+
|
13
|
+
This gem currently requires https://github.com/rnpgp/rnp[librnp] 0.10.0 or newer.
|
10
14
|
|
11
15
|
== Installation
|
12
16
|
|
@@ -28,4 +32,3 @@ Or install it yourself as:
|
|
28
32
|
----
|
29
33
|
gem install rnp
|
30
34
|
----
|
31
|
-
|
data/lib/rnp/ffi/librnp.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# (c) 2018 Ribose Inc.
|
3
|
+
# (c) 2018-2020 Ribose Inc.
|
4
4
|
|
5
5
|
require 'ffi'
|
6
6
|
|
@@ -9,7 +9,156 @@ require 'rnp/error'
|
|
9
9
|
# @api private
|
10
10
|
module LibRnp
|
11
11
|
extend FFI::Library
|
12
|
-
|
12
|
+
|
13
|
+
LOCAL_LIBRNP = File.join(File.dirname(__FILE__), FFI.map_library_name("rnp"))
|
14
|
+
|
15
|
+
ffi_lib [LOCAL_LIBRNP, "rnp-0", "rnp"]
|
16
|
+
|
17
|
+
# some newer APIs that may not be present
|
18
|
+
{
|
19
|
+
# key export
|
20
|
+
rnp_key_export: [%i[pointer pointer uint32], :uint32],
|
21
|
+
# enarmor/dearmor
|
22
|
+
rnp_enarmor: [%i[pointer pointer pointer], :uint32],
|
23
|
+
rnp_dearmor: [%i[pointer pointer], :uint32],
|
24
|
+
# versioning
|
25
|
+
rnp_version_string: [%i[], :string],
|
26
|
+
rnp_version_string_full: [%i[], :string],
|
27
|
+
rnp_version: [%i[], :uint32],
|
28
|
+
rnp_version_for: [%i[uint32 uint32 uint32], :uint32],
|
29
|
+
rnp_version_major: [%i[uint32], :uint32],
|
30
|
+
rnp_version_minor: [%i[uint32], :uint32],
|
31
|
+
rnp_version_patch: [%i[uint32], :uint32],
|
32
|
+
# unload keys
|
33
|
+
rnp_unload_keys: [%i[pointer uint32], :uint32],
|
34
|
+
# remove key
|
35
|
+
rnp_key_remove: [%i[pointer uint32], :uint32],
|
36
|
+
# key properties
|
37
|
+
rnp_key_get_subkey_count: [%i[pointer pointer], :uint32],
|
38
|
+
rnp_key_get_subkey_at: [%i[pointer int pointer], :uint32],
|
39
|
+
rnp_key_get_alg: [%i[pointer pointer], :uint32],
|
40
|
+
rnp_key_get_bits: [%i[pointer pointer], :uint32],
|
41
|
+
rnp_key_get_dsa_qbits: [%i[pointer pointer], :uint32],
|
42
|
+
rnp_key_get_curve: [%i[pointer pointer], :uint32],
|
43
|
+
rnp_key_allows_usage: [%i[pointer string pointer], :uint32],
|
44
|
+
# packet dumping
|
45
|
+
rnp_key_packets_to_json: [%i[pointer bool uint32 pointer], :uint32],
|
46
|
+
rnp_dump_packets_to_json: [%i[pointer uint32 pointer], :uint32],
|
47
|
+
# aead
|
48
|
+
rnp_op_encrypt_set_aead: [%i[pointer string], :uint32],
|
49
|
+
# key generation (op)
|
50
|
+
rnp_op_generate_create: [%i[pointer pointer string], :uint32],
|
51
|
+
rnp_op_generate_subkey_create: [%i[pointer pointer pointer string],
|
52
|
+
:uint32],
|
53
|
+
rnp_op_generate_set_bits: [%i[pointer uint32], :uint32],
|
54
|
+
rnp_op_generate_set_hash: [%i[pointer string], :uint32],
|
55
|
+
rnp_op_generate_set_dsa_qbits: [%i[pointer uint32], :uint32],
|
56
|
+
rnp_op_generate_set_curve: [%i[pointer string], :uint32],
|
57
|
+
rnp_op_generate_set_protection_password: [%i[pointer string], :uint32],
|
58
|
+
rnp_op_generate_set_protection_cipher: [%i[pointer string], :uint32],
|
59
|
+
rnp_op_generate_set_protection_hash: [%i[pointer string], :uint32],
|
60
|
+
rnp_op_generate_set_protection_mode: [%i[pointer string], :uint32],
|
61
|
+
rnp_op_generate_set_protection_iterations: [%i[pointer uint32], :uint32],
|
62
|
+
rnp_op_generate_add_usage: [%i[pointer string], :uint32],
|
63
|
+
rnp_op_generate_clear_usage: [%i[pointer], :uint32],
|
64
|
+
rnp_op_generate_set_userid: [%i[pointer string], :uint32],
|
65
|
+
rnp_op_generate_set_expiration: [%i[pointer uint32], :uint32],
|
66
|
+
rnp_op_generate_add_pref_hash: [%i[pointer string], :uint32],
|
67
|
+
rnp_op_generate_clear_pref_hashes: [%i[pointer], :uint32],
|
68
|
+
rnp_op_generate_add_pref_compression: [%i[pointer string], :uint32],
|
69
|
+
rnp_op_generate_clear_pref_compression: [%i[pointer], :uint32],
|
70
|
+
rnp_op_generate_add_pref_cipher: [%i[pointer string], :uint32],
|
71
|
+
rnp_op_generate_clear_pref_ciphers: [%i[pointer], :uint32],
|
72
|
+
rnp_op_generate_set_pref_keyserver: [%i[pointer pointer], :uint32],
|
73
|
+
rnp_op_generate_execute: [%i[pointer], :uint32],
|
74
|
+
rnp_op_generate_get_key: [%i[pointer pointer], :uint32],
|
75
|
+
rnp_op_generate_destroy: [%i[pointer], :uint32],
|
76
|
+
# key generation (shortcuts)
|
77
|
+
rnp_generate_key_rsa: [%i[pointer uint32 uint32 string string pointer],
|
78
|
+
:uint32],
|
79
|
+
rnp_generate_key_dsa_eg: [%i[pointer uint32 uint32 string string pointer],
|
80
|
+
:uint32],
|
81
|
+
rnp_generate_key_ec: [%i[pointer string string string pointer], :uint32],
|
82
|
+
rnp_generate_key_25519: [%i[pointer string string pointer], :uint32],
|
83
|
+
rnp_generate_key_sm2: [%i[pointer string string pointer], :uint32],
|
84
|
+
rnp_generate_key_ex: [%i[pointer string string uint32 uint32 string string
|
85
|
+
string string pointer], :uint32],
|
86
|
+
rnp_calculate_iterations: [%i[string size_t pointer], :uint32],
|
87
|
+
# debugging
|
88
|
+
rnp_enable_debug: [%i[pointer], :uint32],
|
89
|
+
rnp_disable_debug: [%i[], :uint32],
|
90
|
+
# guess contents
|
91
|
+
rnp_guess_contents: [%i[pointer pointer], :uint32],
|
92
|
+
# features
|
93
|
+
rnp_supports_feature: [%i[string string pointer], :uint32],
|
94
|
+
rnp_supported_features: [%i[string pointer], :uint32],
|
95
|
+
# key revocation
|
96
|
+
rnp_key_is_revoked: [%i[pointer pointer], :uint32],
|
97
|
+
rnp_key_is_compromised: [%i[pointer pointer], :uint32],
|
98
|
+
rnp_key_is_retired: [%i[pointer pointer], :uint32],
|
99
|
+
rnp_key_is_superseded: [%i[pointer pointer], :uint32],
|
100
|
+
rnp_key_get_revocation_reason: [%i[pointer pointer], :uint32],
|
101
|
+
# signatures
|
102
|
+
rnp_key_get_signature_count: [%i[pointer pointer], :uint32],
|
103
|
+
rnp_key_get_signature_at: [%i[pointer size_t pointer], :uint32],
|
104
|
+
rnp_signature_get_alg: [%i[pointer pointer], :uint32],
|
105
|
+
rnp_signature_get_hash_alg: [%i[pointer pointer], :uint32],
|
106
|
+
rnp_signature_get_creation: [%i[pointer pointer], :uint32],
|
107
|
+
rnp_signature_get_keyid: [%i[pointer pointer], :uint32],
|
108
|
+
rnp_signature_get_signer: [%i[pointer pointer], :uint32],
|
109
|
+
rnp_signature_packet_to_json: [%i[pointer uint32 pointer], :uint32],
|
110
|
+
rnp_signature_handle_destroy: [%i[pointer], :uint32],
|
111
|
+
rnp_op_verify_signature_get_handle: [%i[pointer pointer], :uint32],
|
112
|
+
# key uids
|
113
|
+
rnp_key_get_uid_handle_at: [%i[pointer size_t pointer], :uint32],
|
114
|
+
rnp_uid_is_revoked: [%i[pointer pointer], :uint32],
|
115
|
+
rnp_uid_handle_destroy: [%i[pointer], :uint32],
|
116
|
+
rnp_uid_get_signature_count: [%i[pointer pointer], :uint32],
|
117
|
+
rnp_uid_get_signature_at: [%i[pointer size_t pointer], :uint32],
|
118
|
+
# key properties
|
119
|
+
rnp_key_get_creation: [%i[pointer pointer], :uint32],
|
120
|
+
rnp_key_get_expiration: [%i[pointer pointer], :uint32],
|
121
|
+
rnp_key_get_primary_grip: [%i[pointer pointer], :uint32],
|
122
|
+
# output
|
123
|
+
rnp_output_write: [%i[pointer pointer size_t pointer], :uint32],
|
124
|
+
# import
|
125
|
+
rnp_import_keys: [%i[pointer pointer uint32 pointer], :uint32],
|
126
|
+
rnp_import_signatures: [%i[pointer pointer uint32 pointer], :uint32],
|
127
|
+
}.each do |name, signature|
|
128
|
+
present = !ffi_libraries[0].find_function(name.to_s).nil?
|
129
|
+
if !present
|
130
|
+
class_eval do
|
131
|
+
define_singleton_method(name) do |*|
|
132
|
+
raise Rnp::FeatureNotAvailableError, name
|
133
|
+
end
|
134
|
+
end
|
135
|
+
else
|
136
|
+
attach_function name, signature[0], signature[1]
|
137
|
+
end
|
138
|
+
class_eval do
|
139
|
+
const_set("HAVE_#{name.upcase}", present)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
if ffi_libraries[0].find_function('rnp_version_commit_timestamp')
|
144
|
+
attach_function :rnp_version_commit_timestamp, [], :uint64
|
145
|
+
else
|
146
|
+
def self.rnp_version_commit_timestamp
|
147
|
+
0
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
if HAVE_RNP_VERSION && (rnp_version >= rnp_version_for(0, 14, 0) ||
|
152
|
+
rnp_version_commit_timestamp >= 1585833163)
|
153
|
+
callback :rnp_input_reader_t,
|
154
|
+
%i[pointer pointer size_t pointer],
|
155
|
+
:bool
|
156
|
+
else
|
157
|
+
callback :rnp_input_reader_t,
|
158
|
+
%i[pointer pointer size_t],
|
159
|
+
:ssize_t
|
160
|
+
end
|
161
|
+
|
13
162
|
|
14
163
|
callback :rnp_get_key_cb,
|
15
164
|
%i[pointer pointer string string bool],
|
@@ -17,9 +166,6 @@ module LibRnp
|
|
17
166
|
callback :rnp_password_cb,
|
18
167
|
%i[pointer pointer pointer string pointer size_t],
|
19
168
|
:bool
|
20
|
-
callback :rnp_input_reader_t,
|
21
|
-
%i[pointer pointer size_t],
|
22
|
-
:ssize_t
|
23
169
|
callback :rnp_output_writer_t,
|
24
170
|
%i[pointer pointer size_t],
|
25
171
|
:bool
|
@@ -289,37 +435,6 @@ module LibRnp
|
|
289
435
|
%i[pointer],
|
290
436
|
:uint32
|
291
437
|
|
292
|
-
# some newer APIs that may not be present
|
293
|
-
{
|
294
|
-
# key export
|
295
|
-
rnp_key_export: [%i[pointer pointer uint32], :uint32],
|
296
|
-
# enarmor/dearmor
|
297
|
-
rnp_enarmor: [%i[pointer pointer pointer], :uint32],
|
298
|
-
rnp_dearmor: [%i[pointer pointer], :uint32],
|
299
|
-
# versioning
|
300
|
-
rnp_version_string: [%i[], :string],
|
301
|
-
rnp_version_string_full: [%i[], :string],
|
302
|
-
rnp_version: [%i[], :uint32],
|
303
|
-
rnp_version_for: [%i[uint32 uint32 uint32], :uint32],
|
304
|
-
rnp_version_major: [%i[uint32], :uint32],
|
305
|
-
rnp_version_minor: [%i[uint32], :uint32],
|
306
|
-
rnp_version_patch: [%i[uint32], :uint32]
|
307
|
-
}.each do |name, signature|
|
308
|
-
present = ffi_libraries[0].find_function(name.to_s)
|
309
|
-
if !present
|
310
|
-
class_eval do
|
311
|
-
define_singleton_method(name) do |*|
|
312
|
-
raise Rnp::FeatureNotAvailableError, name
|
313
|
-
end
|
314
|
-
end
|
315
|
-
else
|
316
|
-
attach_function name, signature[0], signature[1]
|
317
|
-
end
|
318
|
-
class_eval do
|
319
|
-
const_set("HAVE_#{name.upcase}", present)
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
438
|
RNP_KEY_EXPORT_ARMORED = (1 << 0)
|
324
439
|
RNP_KEY_EXPORT_PUBLIC = (1 << 1)
|
325
440
|
RNP_KEY_EXPORT_SECRET = (1 << 2)
|
@@ -328,11 +443,21 @@ module LibRnp
|
|
328
443
|
RNP_LOAD_SAVE_PUBLIC_KEYS = (1 << 0)
|
329
444
|
RNP_LOAD_SAVE_SECRET_KEYS = (1 << 1)
|
330
445
|
|
446
|
+
RNP_KEY_UNLOAD_PUBLIC = (1 << 0)
|
447
|
+
RNP_KEY_UNLOAD_SECRET = (1 << 1)
|
448
|
+
|
449
|
+
RNP_KEY_REMOVE_PUBLIC = (1 << 0)
|
450
|
+
RNP_KEY_REMOVE_SECRET = (1 << 1)
|
451
|
+
|
331
452
|
RNP_JSON_PUBLIC_MPIS = (1 << 0)
|
332
453
|
RNP_JSON_SECRET_MPIS = (1 << 1)
|
333
454
|
RNP_JSON_SIGNATURES = (1 << 2)
|
334
455
|
RNP_JSON_SIGNATURE_MPIS = (1 << 3)
|
335
456
|
|
457
|
+
RNP_JSON_DUMP_MPI = (1 << 0)
|
458
|
+
RNP_JSON_DUMP_RAW = (1 << 1)
|
459
|
+
RNP_JSON_DUMP_GRIP = (1 << 2)
|
460
|
+
|
336
461
|
RNP_SUCCESS = 0
|
337
462
|
RNP_ERROR_BAD_FORMAT = 0x10000001
|
338
463
|
RNP_ERROR_SIGNATURE_INVALID = 0x12000002
|
data/lib/rnp/input.rb
CHANGED
@@ -9,6 +9,7 @@ require 'ffi'
|
|
9
9
|
require 'rnp/error'
|
10
10
|
require 'rnp/ffi/librnp'
|
11
11
|
require 'rnp/utils'
|
12
|
+
require 'rnp/misc'
|
12
13
|
|
13
14
|
class Rnp
|
14
15
|
# Class used to feed data into RNP.
|
@@ -74,16 +75,35 @@ class Rnp
|
|
74
75
|
end
|
75
76
|
|
76
77
|
# @api private
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
78
|
+
if Rnp.has?("input-reader-cb-no-ssize_t")
|
79
|
+
READER = lambda do |reader, _ctx, buf, buf_len, nread|
|
80
|
+
begin
|
81
|
+
data = reader.call(buf_len)
|
82
|
+
datasz = 0
|
83
|
+
if !data.nil?
|
84
|
+
datasz = data.size unless data.nil?
|
85
|
+
raise Rnp::Error, 'Read exceeded buffer size' if datasz > buf_len
|
86
|
+
buf.write_bytes(data) unless data.nil?
|
87
|
+
end
|
88
|
+
nread.write(:size_t, datasz)
|
89
|
+
return true
|
90
|
+
rescue
|
91
|
+
puts $ERROR_INFO
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
else
|
96
|
+
READER = lambda do |reader, _ctx, buf, buf_len|
|
97
|
+
begin
|
98
|
+
data = reader.call(buf_len)
|
99
|
+
return 0 unless data
|
100
|
+
raise Rnp::Error, 'Read exceeded buffer size' if data.size > buf_len
|
101
|
+
buf.write_bytes(data)
|
102
|
+
return data.size
|
103
|
+
rescue
|
104
|
+
puts $ERROR_INFO
|
105
|
+
return -1
|
106
|
+
end
|
87
107
|
end
|
88
108
|
end
|
89
109
|
|
data/lib/rnp/key.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# (c) 2018 Ribose Inc.
|
3
|
+
# (c) 2018-2020 Ribose Inc.
|
4
4
|
|
5
5
|
require 'ffi'
|
6
6
|
|
7
7
|
require 'rnp/error'
|
8
8
|
require 'rnp/ffi/librnp'
|
9
9
|
require 'rnp/utils'
|
10
|
+
require 'rnp/userid'
|
10
11
|
|
11
12
|
class Rnp
|
12
13
|
# Class that represents a PGP key (potentially encompassing both the public
|
@@ -59,6 +60,13 @@ class Rnp
|
|
59
60
|
string_property(:rnp_key_get_grip)
|
60
61
|
end
|
61
62
|
|
63
|
+
# Get the primary grip of the key (for subkeys)
|
64
|
+
#
|
65
|
+
# @return [String]
|
66
|
+
def primary_grip
|
67
|
+
string_property(:rnp_key_get_primary_grip)
|
68
|
+
end
|
69
|
+
|
62
70
|
# Get the primary userid of the key
|
63
71
|
#
|
64
72
|
# @return [String]
|
@@ -82,6 +90,38 @@ class Rnp
|
|
82
90
|
each_userid.to_a
|
83
91
|
end
|
84
92
|
|
93
|
+
# Enumerate each {UserID} for this key.
|
94
|
+
#
|
95
|
+
# @return [self, Enumerator]
|
96
|
+
def each_uid(&block)
|
97
|
+
block or return enum_for(:uid_iterator)
|
98
|
+
uid_iterator(&block)
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
|
+
# Get a list of {UserID}s for this key.
|
103
|
+
#
|
104
|
+
# @return [Array<UserID>]
|
105
|
+
def uids
|
106
|
+
each_uid.to_a
|
107
|
+
end
|
108
|
+
|
109
|
+
# Enumerate each {Signature} for this key.
|
110
|
+
#
|
111
|
+
# @return [self, Enumerator]
|
112
|
+
def each_signature(&block)
|
113
|
+
block or return enum_for(:signature_iterator)
|
114
|
+
signature_iterator(&block)
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
# Get a list of {Signature}s for this key.
|
119
|
+
#
|
120
|
+
# @return [Array<Signature>]
|
121
|
+
def signatures
|
122
|
+
each_signature.to_a
|
123
|
+
end
|
124
|
+
|
85
125
|
# Add a userid to a key.
|
86
126
|
#
|
87
127
|
# @param userid [String] the userid to add
|
@@ -265,6 +305,134 @@ class Rnp
|
|
265
305
|
end
|
266
306
|
end
|
267
307
|
|
308
|
+
# Unload this key.
|
309
|
+
#
|
310
|
+
# @note When both the public and secret portions of this key have been
|
311
|
+
# unloaded, you should no longer interact with this object.
|
312
|
+
#
|
313
|
+
# @param unload_public [Boolean] if true then the public key will be
|
314
|
+
# unloaded
|
315
|
+
# @param unload_secret [Boolean] if true then the secret key will be
|
316
|
+
# unloaded
|
317
|
+
# @return [void]
|
318
|
+
def unload(unload_public: true, unload_secret: true)
|
319
|
+
flags = 0
|
320
|
+
flags |= LibRnp::RNP_KEY_REMOVE_PUBLIC if unload_public
|
321
|
+
flags |= LibRnp::RNP_KEY_REMOVE_SECRET if unload_secret
|
322
|
+
Rnp.call_ffi(:rnp_key_remove, @ptr, flags)
|
323
|
+
end
|
324
|
+
|
325
|
+
# Enumerate each subkey for this key.
|
326
|
+
#
|
327
|
+
# @return [self, Enumerator]
|
328
|
+
def each_subkey(&block)
|
329
|
+
block or return enum_for(:subkey_iterator)
|
330
|
+
subkey_iterator(&block)
|
331
|
+
self
|
332
|
+
end
|
333
|
+
|
334
|
+
# Get a list of all subkeys for this key.
|
335
|
+
#
|
336
|
+
# @return [Array<Key>]
|
337
|
+
def subkeys
|
338
|
+
each_subkey.to_a
|
339
|
+
end
|
340
|
+
|
341
|
+
# Get the type of this key (RSA, etc).
|
342
|
+
#
|
343
|
+
# @return [String]
|
344
|
+
def type
|
345
|
+
string_property(:rnp_key_get_alg)
|
346
|
+
end
|
347
|
+
|
348
|
+
# Get the bit length for this key.
|
349
|
+
#
|
350
|
+
# @return [Integer]
|
351
|
+
def bits
|
352
|
+
pbits = FFI::MemoryPointer.new(:uint32)
|
353
|
+
Rnp.call_ffi(:rnp_key_get_bits, @ptr, pbits)
|
354
|
+
pbits.read(:uint32)
|
355
|
+
end
|
356
|
+
|
357
|
+
# Get the bit length for the q parameter of this DSA key.
|
358
|
+
#
|
359
|
+
# @return [Integer]
|
360
|
+
def qbits
|
361
|
+
pbits = FFI::MemoryPointer.new(:uint32)
|
362
|
+
Rnp.call_ffi(:rnp_key_get_dsa_qbits, @ptr, pbits)
|
363
|
+
pbits.read(:uint32)
|
364
|
+
end
|
365
|
+
|
366
|
+
# Get the curve of this EC key.
|
367
|
+
#
|
368
|
+
# @return [String]
|
369
|
+
def curve
|
370
|
+
string_property(:rnp_key_get_curve)
|
371
|
+
end
|
372
|
+
|
373
|
+
# Query whether this key can be used to perform a certain operation.
|
374
|
+
#
|
375
|
+
# @param op [String,Symbol] the operation to query (sign, etc)
|
376
|
+
# @return [Boolean]
|
377
|
+
def can?(op)
|
378
|
+
pvalue = FFI::MemoryPointer.new(:bool)
|
379
|
+
Rnp.call_ffi(:rnp_key_allows_usage, @ptr, op.to_s, pvalue)
|
380
|
+
pvalue.read(:bool)
|
381
|
+
end
|
382
|
+
|
383
|
+
# Check if this has been revoked.
|
384
|
+
#
|
385
|
+
# @return [Boolean]
|
386
|
+
def revoked?
|
387
|
+
bool_property(:rnp_key_is_revoked)
|
388
|
+
end
|
389
|
+
|
390
|
+
# Check if this revoked key's material was compromised.
|
391
|
+
#
|
392
|
+
# @return [Boolean]
|
393
|
+
def compromised?
|
394
|
+
bool_property(:rnp_key_is_compromised)
|
395
|
+
end
|
396
|
+
|
397
|
+
# Check if this revoked key was retired.
|
398
|
+
#
|
399
|
+
# @return [Boolean]
|
400
|
+
def retired?
|
401
|
+
bool_property(:rnp_key_is_retired)
|
402
|
+
end
|
403
|
+
|
404
|
+
# Check if this revoked key was superseded by another key.
|
405
|
+
#
|
406
|
+
# @return [Boolean]
|
407
|
+
def superseded?
|
408
|
+
bool_property(:rnp_key_is_superseded)
|
409
|
+
end
|
410
|
+
|
411
|
+
# Retrieve the reason for revoking this key, if any.
|
412
|
+
#
|
413
|
+
# @return [String]
|
414
|
+
def revocation_reason
|
415
|
+
string_property(:rnp_key_get_revocation_reason)
|
416
|
+
end
|
417
|
+
|
418
|
+
# Retrieve the creation time of the key
|
419
|
+
#
|
420
|
+
# @return [Time]
|
421
|
+
def creation_time
|
422
|
+
ptime = FFI::MemoryPointer.new(:uint32)
|
423
|
+
Rnp.call_ffi(:rnp_key_get_creation, @ptr, ptime)
|
424
|
+
Time.at(ptime.read(:uint32))
|
425
|
+
end
|
426
|
+
|
427
|
+
# Retrieve the expiration time of the key
|
428
|
+
#
|
429
|
+
# @return [Time]
|
430
|
+
def expiration_time
|
431
|
+
ptime = FFI::MemoryPointer.new(:uint32)
|
432
|
+
Rnp.call_ffi(:rnp_key_get_expiration, @ptr, ptime)
|
433
|
+
Time.at(ptime.read(:uint32))
|
434
|
+
end
|
435
|
+
|
268
436
|
private
|
269
437
|
|
270
438
|
def string_property(func)
|
@@ -313,6 +481,40 @@ class Rnp
|
|
313
481
|
end
|
314
482
|
end
|
315
483
|
|
484
|
+
def uid_iterator
|
485
|
+
pcount = FFI::MemoryPointer.new(:size_t)
|
486
|
+
Rnp.call_ffi(:rnp_key_get_uid_count, @ptr, pcount)
|
487
|
+
count = pcount.read(:size_t)
|
488
|
+
pptr = FFI::MemoryPointer.new(:pointer)
|
489
|
+
(0...count).each do |i|
|
490
|
+
Rnp.call_ffi(:rnp_key_get_uid_handle_at, @ptr, i, pptr)
|
491
|
+
begin
|
492
|
+
phandle = pptr.read_pointer
|
493
|
+
puserid = nil
|
494
|
+
next if phandle.nil?
|
495
|
+
Rnp.call_ffi(:rnp_key_get_uid_at, @ptr, i, pptr)
|
496
|
+
puserid = pptr.read_pointer
|
497
|
+
yield UserID.new(phandle, puserid.read_string) unless puserid.null?
|
498
|
+
phandle = nil
|
499
|
+
ensure
|
500
|
+
LibRnp.rnp_uid_handle_destroy(phandle)
|
501
|
+
LibRnp.rnp_buffer_destroy(puserid)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
def signature_iterator
|
507
|
+
pcount = FFI::MemoryPointer.new(:size_t)
|
508
|
+
Rnp.call_ffi(:rnp_key_get_signature_count, @ptr, pcount)
|
509
|
+
count = pcount.read(:size_t)
|
510
|
+
pptr = FFI::MemoryPointer.new(:pointer)
|
511
|
+
(0...count).each do |i|
|
512
|
+
Rnp.call_ffi(:rnp_key_get_signature_at, @ptr, i, pptr)
|
513
|
+
psig = pptr.read_pointer
|
514
|
+
yield Signature.new(psig) unless psig.null?
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
316
518
|
def export(public_key: false, secret_key: false, with_subkeys: false, armored: true, output: nil)
|
317
519
|
flags = 0
|
318
520
|
flags |= LibRnp::RNP_KEY_EXPORT_ARMORED if armored
|
@@ -321,6 +523,20 @@ class Rnp
|
|
321
523
|
flags |= LibRnp::RNP_KEY_EXPORT_SUBKEYS if with_subkeys
|
322
524
|
Rnp.call_ffi(:rnp_key_export, @ptr, output.ptr, flags)
|
323
525
|
end
|
526
|
+
|
527
|
+
def subkey_iterator
|
528
|
+
pcount = FFI::MemoryPointer.new(:size_t)
|
529
|
+
Rnp.call_ffi(:rnp_key_get_subkey_count, @ptr, pcount)
|
530
|
+
count = pcount.read(:size_t)
|
531
|
+
pptr = FFI::MemoryPointer.new(:pointer)
|
532
|
+
(0...count).each do |i|
|
533
|
+
Rnp.call_ffi(:rnp_key_get_subkey_at, @ptr, i, pptr)
|
534
|
+
begin
|
535
|
+
psubkey = pptr.read_pointer
|
536
|
+
yield Rnp::Key.new(psubkey) unless psubkey.null?
|
537
|
+
end
|
538
|
+
end
|
539
|
+
end
|
324
540
|
end # class
|
325
541
|
end # class
|
326
542
|
|