rnp 1.0.4 → 1.0.5
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.
- 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
|
|