gpgme-ffi 3.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.
- data/examples/edit.rb +77 -0
- data/examples/genkey.rb +55 -0
- data/examples/keylist.rb +7 -0
- data/examples/roundtrip.rb +42 -0
- data/examples/sign.rb +31 -0
- data/examples/verify.rb +8 -0
- data/ext/gpgme/Makefile.in +55 -0
- data/ext/gpgme/extconf.rb +8 -0
- data/ext/gpgme/extract_enums.rb +88 -0
- data/ext/gpgme/gpgme-1.3.1.tar.bz2 +0 -0
- data/ext/gpgme/libassuan-2.0.2.tar.bz2 +0 -0
- data/ext/gpgme/libgpg-error-1.10.tar.bz2 +0 -0
- data/ext/gpgme/libgpgme_gem.so +0 -0
- data/lib/gpgme/compat.rb +48 -0
- data/lib/gpgme/constants.rb +187 -0
- data/lib/gpgme/crypto.rb +357 -0
- data/lib/gpgme/ctx.rb +462 -0
- data/lib/gpgme/data.rb +189 -0
- data/lib/gpgme/engine.rb +76 -0
- data/lib/gpgme/error.rb +66 -0
- data/lib/gpgme/ffi/ctx.rb +36 -0
- data/lib/gpgme/ffi/data.rb +24 -0
- data/lib/gpgme/ffi/decrypt_result.rb +14 -0
- data/lib/gpgme/ffi/encrypt_result.rb +22 -0
- data/lib/gpgme/ffi/engine_info.rb +17 -0
- data/lib/gpgme/ffi/enums.rb +687 -0
- data/lib/gpgme/ffi/functions.rb +364 -0
- data/lib/gpgme/ffi/import_result.rb +35 -0
- data/lib/gpgme/ffi/import_status.rb +15 -0
- data/lib/gpgme/ffi/invalid_key.rb +14 -0
- data/lib/gpgme/ffi/key.rb +60 -0
- data/lib/gpgme/ffi/key_sig.rb +20 -0
- data/lib/gpgme/ffi/library.rb +279 -0
- data/lib/gpgme/ffi/meta.rb +57 -0
- data/lib/gpgme/ffi/new_signature.rb +18 -0
- data/lib/gpgme/ffi/sig_notation.rb +12 -0
- data/lib/gpgme/ffi/sign_result.rb +33 -0
- data/lib/gpgme/ffi/signature.rb +35 -0
- data/lib/gpgme/ffi/sub_key.rb +27 -0
- data/lib/gpgme/ffi/trust_item.rb +31 -0
- data/lib/gpgme/ffi/user_id.rb +30 -0
- data/lib/gpgme/ffi/verify_result.rb +22 -0
- data/lib/gpgme/ffi.rb +22 -0
- data/lib/gpgme/io_callbacks.rb +21 -0
- data/lib/gpgme/key.rb +242 -0
- data/lib/gpgme/key_common.rb +43 -0
- data/lib/gpgme/key_sig.rb +35 -0
- data/lib/gpgme/misc.rb +66 -0
- data/lib/gpgme/signature.rb +85 -0
- data/lib/gpgme/sub_key.rb +58 -0
- data/lib/gpgme/user_id.rb +20 -0
- data/lib/gpgme/version.rb +3 -0
- data/lib/gpgme.rb +106 -0
- data/test/crypto_test.rb +246 -0
- data/test/ctx_test.rb +432 -0
- data/test/data_test.rb +129 -0
- data/test/files/testkey_pub.gpg +52 -0
- data/test/files/testkey_sec.gpg +54 -0
- data/test/gpgme_test.rb +12 -0
- data/test/key_test.rb +209 -0
- data/test/signature_test.rb +52 -0
- data/test/sub_key_test.rb +48 -0
- data/test/support/resources.rb +516 -0
- data/test/test_helper.rb +84 -0
- metadata +203 -0
data/test/crypto_test.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'test_helper'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
describe GPGME::Crypto do
|
6
|
+
before do
|
7
|
+
skip unless GPGME::Engine.check_version GPGME::PROTOCOL_OpenPGP
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "default options functionality" do
|
11
|
+
it "allows operation from instances normally" do
|
12
|
+
crypto = GPGME::Crypto.new
|
13
|
+
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
|
14
|
+
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can set default options when using the instance way" do
|
18
|
+
crypto = GPGME::Crypto.new :always_trust => true
|
19
|
+
encrypted = crypto.encrypt TEXT[:plain], :recipients => KEYS.first[:sha]
|
20
|
+
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
|
21
|
+
end
|
22
|
+
|
23
|
+
it "but they can still be overwritten" do
|
24
|
+
crypto = GPGME::Crypto.new :always_trust => false
|
25
|
+
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
|
26
|
+
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "roundtrip encryption/decryption" do
|
31
|
+
it "does the roundtrip encrypting" do
|
32
|
+
crypto = GPGME::Crypto.new
|
33
|
+
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
|
34
|
+
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
|
35
|
+
end
|
36
|
+
|
37
|
+
it "does so even with armored encrypted stuff" do
|
38
|
+
crypto = GPGME::Crypto.new
|
39
|
+
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :armor => true
|
40
|
+
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe :encrypt do
|
45
|
+
it "should raise an error if the recipients aren't trusted" do
|
46
|
+
assert_raises GPGME::Error::General do
|
47
|
+
GPGME::Crypto.new.encrypt TEXT[:plain]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "doesn't raise an error and returns something when encrypting nothing" do
|
52
|
+
data = GPGME::Crypto.new.encrypt nil, :always_trust => true
|
53
|
+
refute_empty data.read
|
54
|
+
data = GPGME::Crypto.new.encrypt "", :always_trust => true
|
55
|
+
refute_empty data.read
|
56
|
+
end
|
57
|
+
|
58
|
+
it "can specify which key(s) to use for encrypting with a string" do
|
59
|
+
crypto = GPGME::Crypto.new :always_trust => true
|
60
|
+
key = KEYS.last
|
61
|
+
encrypted = crypto.encrypt TEXT[:plain], :recipients => key[:sha]
|
62
|
+
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
|
63
|
+
|
64
|
+
remove_key key
|
65
|
+
encrypted.seek 0
|
66
|
+
assert_raises GPGME::Error::DecryptFailed do
|
67
|
+
crypto.decrypt(encrypted)
|
68
|
+
end
|
69
|
+
import_key key
|
70
|
+
end
|
71
|
+
|
72
|
+
it "can specify which key to use for encrypting with a Key object" do
|
73
|
+
crypto = GPGME::Crypto.new :always_trust => true
|
74
|
+
key = KEYS.last
|
75
|
+
real_key = GPGME::Key.find(:public, key[:sha]).first
|
76
|
+
|
77
|
+
encrypted = crypto.encrypt TEXT[:plain], :recipients => real_key
|
78
|
+
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
|
79
|
+
|
80
|
+
remove_key key
|
81
|
+
encrypted.seek 0
|
82
|
+
assert_raises GPGME::Error::DecryptFailed do
|
83
|
+
crypto.decrypt(encrypted)
|
84
|
+
end
|
85
|
+
import_key key
|
86
|
+
end
|
87
|
+
|
88
|
+
it "can also sign at the same time" do
|
89
|
+
crypto = GPGME::Crypto.new :always_trust => true
|
90
|
+
encrypted = crypto.encrypt TEXT[:plain], :sign => true
|
91
|
+
signatures = 0
|
92
|
+
|
93
|
+
crypto.verify(encrypted) do |signature|
|
94
|
+
assert_instance_of GPGME::Signature, signature
|
95
|
+
signatures += 1
|
96
|
+
end
|
97
|
+
|
98
|
+
assert_equal 1, signatures
|
99
|
+
end
|
100
|
+
|
101
|
+
it "can be signed by more than one person" do
|
102
|
+
crypto = GPGME::Crypto.new :always_trust => true
|
103
|
+
encrypted = crypto.encrypt TEXT[:plain], :sign => true, :signers => KEYS.map{|k| k[:sha]}
|
104
|
+
signatures = 0
|
105
|
+
|
106
|
+
crypto.verify(encrypted) do |signature|
|
107
|
+
assert_instance_of GPGME::Signature, signature
|
108
|
+
signatures += 1
|
109
|
+
end
|
110
|
+
|
111
|
+
assert_equal 4, signatures
|
112
|
+
end
|
113
|
+
|
114
|
+
it "outputs to a file if specified" do
|
115
|
+
crypto = GPGME::Crypto.new :always_trust => true
|
116
|
+
file = Tempfile.new "test"
|
117
|
+
crypto.encrypt TEXT[:plain], :output => file
|
118
|
+
file_contents = file.read
|
119
|
+
file.seek 0
|
120
|
+
|
121
|
+
refute_empty file_contents
|
122
|
+
assert_equal TEXT[:plain], crypto.decrypt(file).read
|
123
|
+
end
|
124
|
+
|
125
|
+
# TODO find how to test
|
126
|
+
# it "raises GPGME::Error::UnusablePublicKey"
|
127
|
+
# it "raises GPGME::Error::UnusableSecretKey"
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "symmetric encryption/decryption" do
|
131
|
+
it "requires a password to encrypt" do
|
132
|
+
assert_raises GPGME::Error::BadPassphrase do
|
133
|
+
GPGME::Crypto.new.encrypt TEXT[:plain], :symmetric => true
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it "requires a password to decrypt" do
|
138
|
+
crypto = GPGME::Crypto.new
|
139
|
+
encrypted_data = crypto.encrypt TEXT[:plain],
|
140
|
+
:symmetric => true, :password => "gpgme"
|
141
|
+
|
142
|
+
assert_raises GPGME::Error::BadPassphrase do
|
143
|
+
crypto.decrypt encrypted_data
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it "can encrypt and decrypt with the same password" do
|
148
|
+
crypto = GPGME::Crypto.new :symmetric => true, :password => "gpgme"
|
149
|
+
encrypted_data = crypto.encrypt TEXT[:plain]
|
150
|
+
plain = crypto.decrypt encrypted_data
|
151
|
+
|
152
|
+
assert_equal "Hi there", plain.read
|
153
|
+
end
|
154
|
+
|
155
|
+
it "but breaks with different ones" do
|
156
|
+
crypto = GPGME::Crypto.new
|
157
|
+
encrypted_data = crypto.encrypt TEXT[:plain],
|
158
|
+
:symmetric => true, :password => "gpgme"
|
159
|
+
|
160
|
+
assert_raises GPGME::Error::DecryptFailed do
|
161
|
+
crypto.decrypt encrypted_data, :password => "wrong one"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe :decrypt do
|
167
|
+
it "decrypts encrypted stuff" do
|
168
|
+
assert_equal TEXT[:plain], GPGME::Crypto.new.decrypt(TEXT[:encrypted]).read
|
169
|
+
end
|
170
|
+
|
171
|
+
it "will not get into the signatures block if there's none" do
|
172
|
+
GPGME::Crypto.new.decrypt(TEXT[:encrypted]) do |signature|
|
173
|
+
flunk "If I'm here means there was some signature"
|
174
|
+
end
|
175
|
+
pass
|
176
|
+
end
|
177
|
+
|
178
|
+
it "will get signature elements if the encrypted thing was signed" do
|
179
|
+
signatures = 0
|
180
|
+
GPGME::Crypto.new.decrypt(TEXT[:signed]) do |signature|
|
181
|
+
assert_instance_of GPGME::Signature, signature
|
182
|
+
signatures += 1
|
183
|
+
end
|
184
|
+
assert_equal 1, signatures
|
185
|
+
end
|
186
|
+
|
187
|
+
it "writes to the output if passed" do
|
188
|
+
buffer = GPGME::Data.new
|
189
|
+
GPGME::Crypto.new.decrypt(TEXT[:encrypted], :output => buffer)
|
190
|
+
assert_equal TEXT[:plain], buffer.read
|
191
|
+
end
|
192
|
+
|
193
|
+
# TODO find ways to test this
|
194
|
+
# it "raises UnsupportedAlgorithm"
|
195
|
+
# it "raises WrongKeyUsage"
|
196
|
+
|
197
|
+
it "raises DecryptFailed when the decrypting key isn't available" do
|
198
|
+
assert_raises GPGME::Error::DecryptFailed do
|
199
|
+
GPGME::Crypto.new.decrypt(TEXT[:unavailable])
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe :sign do
|
205
|
+
it "signs normal strings" do
|
206
|
+
crypto = GPGME::Crypto.new
|
207
|
+
signatures = 0
|
208
|
+
sign = crypto.sign "Hi there"
|
209
|
+
|
210
|
+
crypto.verify(sign) do |signature|
|
211
|
+
assert_instance_of GPGME::Signature, signature
|
212
|
+
assert signature.valid?
|
213
|
+
signatures += 1
|
214
|
+
end
|
215
|
+
|
216
|
+
assert_equal 1, signatures
|
217
|
+
end
|
218
|
+
|
219
|
+
# TODO Find how to import an expired public key
|
220
|
+
# it "raises an error if trying to sign with an expired key" do
|
221
|
+
# with_key EXPIRED_KEY do
|
222
|
+
# crypto = GPGME::Crypto.new
|
223
|
+
# assert_raises GPGME::Error::General do
|
224
|
+
# sign = crypto.sign "Hi there", :signer => EXPIRED_KEY[:sha]
|
225
|
+
# end
|
226
|
+
# end
|
227
|
+
# end
|
228
|
+
|
229
|
+
it "selects who to sign for" do
|
230
|
+
crypto = GPGME::Crypto.new
|
231
|
+
sign = crypto.sign "Hi there", :signer => KEYS.last[:sha]
|
232
|
+
key = GPGME::Key.get(KEYS.last[:sha])
|
233
|
+
|
234
|
+
signatures = 0
|
235
|
+
|
236
|
+
crypto.verify(sign) do |signature|
|
237
|
+
assert_instance_of GPGME::Signature, signature
|
238
|
+
assert_equal key, signature.key
|
239
|
+
signatures += 1
|
240
|
+
end
|
241
|
+
|
242
|
+
assert_equal 1, signatures
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
end
|
data/test/ctx_test.rb
ADDED
@@ -0,0 +1,432 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
describe GPGME::Ctx do
|
5
|
+
before do
|
6
|
+
skip unless GPGME::Engine.check_version GPGME::PROTOCOL_OpenPGP
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can instantiate" do
|
10
|
+
assert_instance_of GPGME::Ctx, GPGME::Ctx.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it "doesn't close itself" do
|
14
|
+
GPGME.expects(:gpgme_release).never
|
15
|
+
GPGME::Ctx.new
|
16
|
+
end
|
17
|
+
|
18
|
+
it "closes itself if called with a block" do
|
19
|
+
GPGME.expects(:gpgme_release).with(anything)
|
20
|
+
GPGME::Ctx.new { |ctx| }
|
21
|
+
end
|
22
|
+
|
23
|
+
it "can be closed with the release method" do
|
24
|
+
GPGME.expects(:gpgme_release).with(anything)
|
25
|
+
ctx = GPGME::Ctx.new
|
26
|
+
ctx.release
|
27
|
+
end
|
28
|
+
|
29
|
+
describe :new do
|
30
|
+
# We consider :armor, :protocol, :textmode and :keylist_mode as tested
|
31
|
+
# with the other tests of this file. Here we test the rest
|
32
|
+
|
33
|
+
it ":password sets the password for the key" do
|
34
|
+
with_key PASSWORD_KEY do
|
35
|
+
input = GPGME::Data.new(TEXT[:passwored])
|
36
|
+
output = GPGME::Data.new
|
37
|
+
|
38
|
+
GPGME::Ctx.new(:password => 'gpgme') do |ctx|
|
39
|
+
ctx.decrypt_verify input, output
|
40
|
+
end
|
41
|
+
|
42
|
+
output.seek 0
|
43
|
+
assert_equal "Hi there", output.read.chomp
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it ":passphrase_callback sets the callback for the password" do
|
48
|
+
def test_pass_func(obj,par2,par3,prev_was_bad,fd)
|
49
|
+
# prev_was_bad is 0 the first time, 1 the rest
|
50
|
+
if @var == 0
|
51
|
+
assert_equal 0, prev_was_bad
|
52
|
+
else
|
53
|
+
assert_equal 1, prev_was_bad
|
54
|
+
end
|
55
|
+
|
56
|
+
@var += 1
|
57
|
+
|
58
|
+
io = ::FFI::IO.for_fd(fd, 'w')
|
59
|
+
io.puts "wrong pasword"
|
60
|
+
io.flush
|
61
|
+
end
|
62
|
+
|
63
|
+
def with_correct_pass_func(obj,par2,par3,prev_was_bad,fd)
|
64
|
+
io = ::FFI::IO.for_fd(fd, 'w')
|
65
|
+
io.puts "gpgme"
|
66
|
+
io.flush
|
67
|
+
end
|
68
|
+
|
69
|
+
with_key PASSWORD_KEY do
|
70
|
+
input = GPGME::Data.new(TEXT[:passwored])
|
71
|
+
output = GPGME::Data.new
|
72
|
+
@var = 0
|
73
|
+
|
74
|
+
assert_raises GPGME::Error::BadPassphrase do
|
75
|
+
GPGME::Ctx.new(:passphrase_callback => method(:test_pass_func)) do |ctx|
|
76
|
+
ctx.decrypt_verify input, output
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Since we request the key 3 times, we should've gone through the
|
81
|
+
# callback 3 times.
|
82
|
+
assert_equal 3, @var
|
83
|
+
|
84
|
+
input.seek 0
|
85
|
+
output.seek 0
|
86
|
+
|
87
|
+
# Shouldn't crash
|
88
|
+
GPGME::Ctx.new(:passphrase_callback => method(:with_correct_pass_func)) do |ctx|
|
89
|
+
ctx.decrypt_verify input, output
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it ":passphrase_callback_value passes a value to the callback function" do
|
95
|
+
def checking_value(value,par2,par3,par4,fd)
|
96
|
+
assert_equal "superman", value
|
97
|
+
io = ::FFI::IO.for_fd(fd, 'w')
|
98
|
+
io.puts "gpgme"
|
99
|
+
io.flush
|
100
|
+
end
|
101
|
+
|
102
|
+
with_key PASSWORD_KEY do
|
103
|
+
input = GPGME::Data.new(TEXT[:passwored])
|
104
|
+
output = GPGME::Data.new
|
105
|
+
|
106
|
+
options = {
|
107
|
+
:passphrase_callback => method(:checking_value),
|
108
|
+
:passphrase_callback_value => "superman"
|
109
|
+
}
|
110
|
+
|
111
|
+
GPGME::Ctx.new(options) do |ctx|
|
112
|
+
ctx.decrypt_verify input, output
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# TODO Don't know how to use them yet
|
118
|
+
# it ":progress_callback"
|
119
|
+
# it ":progress_callback_value"
|
120
|
+
end
|
121
|
+
|
122
|
+
describe :armor do
|
123
|
+
it "sets false by default" do
|
124
|
+
ctx = GPGME::Ctx.new
|
125
|
+
refute ctx.armor
|
126
|
+
end
|
127
|
+
|
128
|
+
it "can set" do
|
129
|
+
ctx = GPGME::Ctx.new
|
130
|
+
ctx.armor = true
|
131
|
+
assert ctx.armor
|
132
|
+
end
|
133
|
+
|
134
|
+
it "can set and get armor" do
|
135
|
+
ctx = GPGME::Ctx.new(:armor => false)
|
136
|
+
refute ctx.armor
|
137
|
+
ctx = GPGME::Ctx.new(:armor => true)
|
138
|
+
assert ctx.armor
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe :protocol do
|
143
|
+
it "sets 0 by default" do
|
144
|
+
ctx = GPGME::Ctx.new
|
145
|
+
assert_equal 0, ctx.protocol
|
146
|
+
end
|
147
|
+
|
148
|
+
it "can set" do
|
149
|
+
ctx = GPGME::Ctx.new
|
150
|
+
ctx.protocol = 1
|
151
|
+
assert_equal 1, ctx.protocol
|
152
|
+
end
|
153
|
+
|
154
|
+
it "can set and get protocol" do
|
155
|
+
ctx = GPGME::Ctx.new(:protocol => GPGME::PROTOCOL_OpenPGP)
|
156
|
+
assert_equal GPGME::PROTOCOL_OpenPGP, ctx.protocol
|
157
|
+
end
|
158
|
+
|
159
|
+
it "doesn't allow just any value" do
|
160
|
+
assert_raises GPGME::Error::InvalidValue do
|
161
|
+
ctx = GPGME::Ctx.new(:protocol => -200)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe :textmode do
|
167
|
+
it "sets false by default" do
|
168
|
+
ctx = GPGME::Ctx.new
|
169
|
+
refute ctx.textmode
|
170
|
+
end
|
171
|
+
|
172
|
+
it "can set" do
|
173
|
+
ctx = GPGME::Ctx.new
|
174
|
+
ctx.textmode = true
|
175
|
+
assert ctx.textmode
|
176
|
+
end
|
177
|
+
|
178
|
+
it "can set and get textmode" do
|
179
|
+
ctx = GPGME::Ctx.new(:textmode => false)
|
180
|
+
refute ctx.textmode
|
181
|
+
ctx = GPGME::Ctx.new(:textmode => true)
|
182
|
+
assert ctx.textmode
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe :keylist_mode do
|
187
|
+
it "sets local by default" do
|
188
|
+
ctx = GPGME::Ctx.new
|
189
|
+
assert_equal GPGME::KEYLIST_MODE_LOCAL, ctx.keylist_mode
|
190
|
+
end
|
191
|
+
|
192
|
+
it "can set and get" do
|
193
|
+
ctx = GPGME::Ctx.new(:keylist_mode => GPGME::KEYLIST_MODE_SIGS)
|
194
|
+
assert_equal GPGME::KEYLIST_MODE_SIGS, ctx.keylist_mode
|
195
|
+
end
|
196
|
+
|
197
|
+
it "can set" do
|
198
|
+
ctx = GPGME::Ctx.new
|
199
|
+
ctx.keylist_mode = GPGME::KEYLIST_MODE_SIGS
|
200
|
+
assert_equal GPGME::KEYLIST_MODE_SIGS, ctx.keylist_mode
|
201
|
+
end
|
202
|
+
|
203
|
+
it "allows the four possible values" do
|
204
|
+
[GPGME::KEYLIST_MODE_LOCAL, GPGME::KEYLIST_MODE_EXTERN,
|
205
|
+
GPGME::KEYLIST_MODE_SIGS, GPGME::KEYLIST_MODE_VALIDATE].each do |mode|
|
206
|
+
GPGME::Ctx.new(:keylist_mode => mode)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# It's not crashing?
|
211
|
+
# it "crashes with other values" do
|
212
|
+
# GPGME::Ctx.new(:keylist_mode => -200)
|
213
|
+
# end
|
214
|
+
end
|
215
|
+
|
216
|
+
# describe :set_passphrase_callback do
|
217
|
+
# def test_pass_func(par1,par2,par3,par4,par5)
|
218
|
+
# par1
|
219
|
+
# end
|
220
|
+
|
221
|
+
# test "it sets the passphrase"
|
222
|
+
|
223
|
+
# end
|
224
|
+
|
225
|
+
describe "keylist operations" do
|
226
|
+
it "can return all of the keys" do
|
227
|
+
ctx = GPGME::Ctx.new
|
228
|
+
keys = ctx.keys
|
229
|
+
ctx.release
|
230
|
+
|
231
|
+
assert keys.size >= 4
|
232
|
+
KEYS.each do |key|
|
233
|
+
assert keys.map(&:email).include?(key[:sha])
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
it "can return keys filtering by a pattern" do
|
238
|
+
ctx = GPGME::Ctx.new
|
239
|
+
keys = ctx.keys(KEYS.first[:sha])
|
240
|
+
ctx.release
|
241
|
+
|
242
|
+
assert_equal 1, keys.size
|
243
|
+
assert_equal KEYS.first[:sha], keys.first.email
|
244
|
+
end
|
245
|
+
|
246
|
+
it "can return only secret keys" do
|
247
|
+
ctx = GPGME::Ctx.new
|
248
|
+
keys = ctx.keys(KEYS.first[:sha], true)
|
249
|
+
ctx.release
|
250
|
+
|
251
|
+
assert keys.all?(&:secret?)
|
252
|
+
end
|
253
|
+
|
254
|
+
it "can return only public keys" do
|
255
|
+
ctx = GPGME::Ctx.new
|
256
|
+
keys = ctx.keys(KEYS.first[:sha], false)
|
257
|
+
ctx.release
|
258
|
+
|
259
|
+
refute keys.any?(&:secret?)
|
260
|
+
end
|
261
|
+
|
262
|
+
it "returns only public keys by default" do
|
263
|
+
ctx = GPGME::Ctx.new
|
264
|
+
keys = ctx.keys(KEYS.first[:sha])
|
265
|
+
ctx.release
|
266
|
+
|
267
|
+
refute keys.any?(&:secret?)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "can iterate through them returning only public keys" do
|
271
|
+
GPGME::Ctx.new do |ctx|
|
272
|
+
ctx.each_key do |key|
|
273
|
+
assert_instance_of GPGME::Key, key
|
274
|
+
refute key.secret?
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
it "can iterate through them getting only secret ones" do
|
280
|
+
GPGME::Ctx.new do |ctx|
|
281
|
+
ctx.each_key("", true) do |key|
|
282
|
+
assert_instance_of GPGME::Key, key
|
283
|
+
assert key.secret?
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
it "can iterate through them filtering by pattern" do
|
289
|
+
num = 0
|
290
|
+
GPGME::Ctx.new do |ctx|
|
291
|
+
ctx.each_key(KEYS.first[:sha]) do |key|
|
292
|
+
assert_instance_of GPGME::Key, key
|
293
|
+
assert_equal KEYS.first[:sha], key.email
|
294
|
+
num += 1
|
295
|
+
end
|
296
|
+
end
|
297
|
+
assert_equal 1, num
|
298
|
+
end
|
299
|
+
|
300
|
+
it "can get only a specific key" do
|
301
|
+
GPGME::Ctx.new do |ctx|
|
302
|
+
key = ctx.get_key(KEYS.first[:sha])
|
303
|
+
assert_instance_of GPGME::Key, key
|
304
|
+
assert_equal KEYS.first[:sha], key.email
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
describe "key generation" do
|
310
|
+
it "generates a key according to specifications" do
|
311
|
+
skip "long test" if ENV.include? "QUICK_TESTING"
|
312
|
+
|
313
|
+
key = <<-RUBY
|
314
|
+
<GnupgKeyParms format="internal">
|
315
|
+
Key-Type: DSA
|
316
|
+
Key-Length: 1024
|
317
|
+
Subkey-Type: ELG-E
|
318
|
+
Subkey-Length: 1024
|
319
|
+
Name-Real: Key Tester
|
320
|
+
Name-Comment: with some comments
|
321
|
+
Name-Email: test_generation@example.com
|
322
|
+
Expire-Date: 0
|
323
|
+
Passphrase: wadus
|
324
|
+
</GnupgKeyParms>
|
325
|
+
RUBY
|
326
|
+
|
327
|
+
keys_amount = GPGME::Key.find(:public).size
|
328
|
+
GPGME::Ctx.new do |ctx|
|
329
|
+
ctx.generate_key(key.chomp)
|
330
|
+
end
|
331
|
+
|
332
|
+
assert_equal keys_amount + 1, GPGME::Key.find(:public).size
|
333
|
+
|
334
|
+
GPGME::Key.find(:public, "test_generation@example.com").each do |k|
|
335
|
+
k.delete!(true)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
describe "key export/import" do
|
341
|
+
it "exports and imports all keys when passing an empty string" do
|
342
|
+
original_keys = GPGME::Key.find(:public)
|
343
|
+
export = ""
|
344
|
+
GPGME::Ctx.new do |ctx|
|
345
|
+
export = ctx.export_keys("")
|
346
|
+
end
|
347
|
+
export.seek(0)
|
348
|
+
|
349
|
+
GPGME::Key.find(:public).each{|k| k.delete!(true)}
|
350
|
+
assert_equal 0, GPGME::Key.find(:public).size
|
351
|
+
|
352
|
+
result = GPGME::Key.import(export)
|
353
|
+
current_keys = GPGME::Key.find(:public)
|
354
|
+
assert_equal original_keys.size, current_keys.size
|
355
|
+
assert_equal result.imports.size, current_keys.size
|
356
|
+
assert result.imports.all?{|import| import.status == 1}
|
357
|
+
|
358
|
+
assert_equal original_keys.map(&:sha), original_keys.map(&:sha)
|
359
|
+
|
360
|
+
import_keys # If the test fails for some reason, it won't break others.
|
361
|
+
end
|
362
|
+
|
363
|
+
it "exports only one key" do
|
364
|
+
original_keys = GPGME::Key.find(:public)
|
365
|
+
key = original_keys.first
|
366
|
+
export = ""
|
367
|
+
GPGME::Ctx.new do |ctx|
|
368
|
+
export = ctx.export_keys(key.sha)
|
369
|
+
end
|
370
|
+
export.seek(0)
|
371
|
+
|
372
|
+
key.delete!(true)
|
373
|
+
|
374
|
+
result = GPGME::Key.import(export)
|
375
|
+
assert_equal 1, result.imports.size
|
376
|
+
|
377
|
+
import = result.imports.first
|
378
|
+
|
379
|
+
imported_key = GPGME::Key.find(:public, import.fpr).first
|
380
|
+
assert_equal key.sha, imported_key.sha
|
381
|
+
assert_equal key.email, imported_key.email
|
382
|
+
import_keys # If the test fails for some reason, it won't break others.
|
383
|
+
end
|
384
|
+
|
385
|
+
it "imports keys and can get a result object" do
|
386
|
+
without_key KEYS.last do
|
387
|
+
public_amount = GPGME::Key.find(:public).size
|
388
|
+
secret_amount = GPGME::Key.find(:secret).size
|
389
|
+
|
390
|
+
result = nil
|
391
|
+
GPGME::Ctx.new do |ctx|
|
392
|
+
ctx.import_keys(GPGME::Data.new(KEYS.last[:public]))
|
393
|
+
ctx.import_keys(GPGME::Data.new(KEYS.last[:secret]))
|
394
|
+
|
395
|
+
result = ctx.import_result
|
396
|
+
end
|
397
|
+
|
398
|
+
assert_equal secret_amount + 1, GPGME::Key.find(:secret).size
|
399
|
+
assert_equal public_amount + 1, GPGME::Key.find(:public).size
|
400
|
+
assert_instance_of GPGME::ImportResult, result
|
401
|
+
assert_instance_of GPGME::ImportStatus, result.imports.first
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
describe "deleting/editing of keys" do
|
407
|
+
it "can delete keys" do
|
408
|
+
original_keys = GPGME::Key.find(:public)
|
409
|
+
key = original_keys.first
|
410
|
+
|
411
|
+
GPGME::Ctx.new do |ctx|
|
412
|
+
ctx.delete_key key, true
|
413
|
+
end
|
414
|
+
|
415
|
+
assert_empty GPGME::Key.find(:public, key.sha)
|
416
|
+
import_keys
|
417
|
+
end
|
418
|
+
|
419
|
+
it "raises error if there's a secret key attached but secret key deletion isn't marked" do
|
420
|
+
original_keys = GPGME::Key.find(:public)
|
421
|
+
key = original_keys.first
|
422
|
+
|
423
|
+
assert_raises GPGME::Error::Conflict do
|
424
|
+
GPGME::Ctx.new do |ctx|
|
425
|
+
ctx.delete_key key
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
# Don't know how to test or use edit_key and edit_card
|
432
|
+
end
|