benburkert-gpgme 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/gpgme.rb ADDED
@@ -0,0 +1,108 @@
1
+ $:.push File.expand_path("../..", __FILE__) # C extension is in the root
2
+
3
+ require 'gpgme_n'
4
+
5
+ # TODO without this call one can't GPGME::Ctx.new, find out why
6
+ GPGME::gpgme_check_version(nil)
7
+
8
+ require 'gpgme/constants'
9
+ require 'gpgme/ctx'
10
+ require 'gpgme/data'
11
+ require 'gpgme/error'
12
+ require 'gpgme/io_callbacks'
13
+ require 'gpgme/key_common'
14
+ require 'gpgme/key'
15
+ require 'gpgme/sub_key'
16
+ require 'gpgme/key_sig'
17
+ require 'gpgme/misc'
18
+ require 'gpgme/signature'
19
+ require 'gpgme/user_id'
20
+ require 'gpgme/engine'
21
+ require 'gpgme/crypto'
22
+
23
+ module GPGME
24
+ class << self
25
+
26
+ # From the c extension
27
+ alias pubkey_algo_name gpgme_pubkey_algo_name
28
+ alias hash_algo_name gpgme_hash_algo_name
29
+
30
+ ##
31
+ # Auxiliary method used by all the library to generate exceptions
32
+ # from error codes returned by the C extension.
33
+ def error_to_exception(err)
34
+ case GPGME::gpgme_err_code(err)
35
+ when GPG_ERR_EOF
36
+ EOFError.new
37
+ when GPG_ERR_NO_ERROR
38
+ nil
39
+ when GPG_ERR_GENERAL
40
+ Error::General.new(err)
41
+ when GPG_ERR_ENOMEM
42
+ Errno::ENOMEM.new
43
+ when GPG_ERR_INV_VALUE
44
+ Error::InvalidValue.new(err)
45
+ when GPG_ERR_UNUSABLE_PUBKEY
46
+ Error::UnusablePublicKey.new(err)
47
+ when GPG_ERR_UNUSABLE_SECKEY
48
+ Error::UnusableSecretKey.new(err)
49
+ when GPG_ERR_NO_DATA
50
+ Error::NoData.new(err)
51
+ when GPG_ERR_CONFLICT
52
+ Error::Conflict.new(err)
53
+ when GPG_ERR_NOT_IMPLEMENTED
54
+ Error::NotImplemented.new(err)
55
+ when GPG_ERR_DECRYPT_FAILED
56
+ Error::DecryptFailed.new(err)
57
+ when GPG_ERR_BAD_PASSPHRASE
58
+ Error::BadPassphrase.new(err)
59
+ when GPG_ERR_CANCELED
60
+ Error::Canceled.new(err)
61
+ when GPG_ERR_INV_ENGINE
62
+ Error::InvalidEngine.new(err)
63
+ when GPG_ERR_AMBIGUOUS_NAME
64
+ Error::AmbiguousName.new(err)
65
+ when GPG_ERR_WRONG_KEY_USAGE
66
+ Error::WrongKeyUsage.new(err)
67
+ when GPG_ERR_CERT_REVOKED
68
+ Error::CertificateRevoked.new(err)
69
+ when GPG_ERR_CERT_EXPIRED
70
+ Error::CertificateExpired.new(err)
71
+ when GPG_ERR_NO_CRL_KNOWN
72
+ Error::NoCRLKnown.new(err)
73
+ when GPG_ERR_NO_POLICY_MATCH
74
+ Error::NoPolicyMatch.new(err)
75
+ when GPG_ERR_NO_SECKEY
76
+ Error::NoSecretKey.new(err)
77
+ when GPG_ERR_MISSING_CERT
78
+ Error::MissingCertificate.new(err)
79
+ when GPG_ERR_BAD_CERT_CHAIN
80
+ Error::BadCertificateChain.new(err)
81
+ when GPG_ERR_UNSUPPORTED_ALGORITHM
82
+ Error::UnsupportedAlgorithm.new(err)
83
+ when GPG_ERR_BAD_SIGNATURE
84
+ Error::BadSignature.new(err)
85
+ when GPG_ERR_NO_PUBKEY
86
+ Error::NoPublicKey.new(err)
87
+ else
88
+ Error.new(err)
89
+ end
90
+ end
91
+
92
+ ##
93
+ # TODO find out what it does, can't seem to find a proper parameter that
94
+ # returns something other than nil.
95
+ def check_version(options = nil)
96
+ version = nil
97
+ if options.kind_of?(String)
98
+ version = options
99
+ elsif options.include?(:version)
100
+ version = options[:version]
101
+ end
102
+ unless GPGME::gpgme_check_version(version)
103
+ raise Error::InvalidVersion.new
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,242 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'test_helper'
3
+ require 'tempfile'
4
+
5
+ describe GPGME::Crypto do
6
+ describe "default options functionality" do
7
+ it "allows operation from instances normally" do
8
+ crypto = GPGME::Crypto.new
9
+ encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
10
+ assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
11
+ end
12
+
13
+ it "can set default options when using the instance way" do
14
+ crypto = GPGME::Crypto.new :always_trust => true
15
+ encrypted = crypto.encrypt TEXT[:plain], :recipients => KEYS.first[:sha]
16
+ assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
17
+ end
18
+
19
+ it "but they can still be overwritten" do
20
+ crypto = GPGME::Crypto.new :always_trust => false
21
+ encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
22
+ assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
23
+ end
24
+ end
25
+
26
+ describe "roundtrip encryption/decryption" do
27
+ it "does the roundtrip encrypting" do
28
+ crypto = GPGME::Crypto.new
29
+ encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
30
+ assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
31
+ end
32
+
33
+ it "does so even with armored encrypted stuff" do
34
+ crypto = GPGME::Crypto.new
35
+ encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :armor => true
36
+ assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
37
+ end
38
+ end
39
+
40
+ describe :encrypt do
41
+ it "should raise an error if the recipients aren't trusted" do
42
+ assert_raises GPGME::Error::General do
43
+ GPGME::Crypto.new.encrypt TEXT[:plain]
44
+ end
45
+ end
46
+
47
+ it "doesn't raise an error and returns something when encrypting nothing" do
48
+ data = GPGME::Crypto.new.encrypt nil, :always_trust => true
49
+ refute_empty data.read
50
+ data = GPGME::Crypto.new.encrypt "", :always_trust => true
51
+ refute_empty data.read
52
+ end
53
+
54
+ it "can specify which key(s) to use for encrypting with a string" do
55
+ crypto = GPGME::Crypto.new :always_trust => true
56
+ key = KEYS.last
57
+ encrypted = crypto.encrypt TEXT[:plain], :recipients => key[:sha]
58
+ assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
59
+
60
+ remove_key key
61
+ encrypted.seek 0
62
+ assert_raises GPGME::Error::DecryptFailed do
63
+ crypto.decrypt(encrypted)
64
+ end
65
+ import_key key
66
+ end
67
+
68
+ it "can specify which key to use for encrypting with a Key object" do
69
+ crypto = GPGME::Crypto.new :always_trust => true
70
+ key = KEYS.last
71
+ real_key = GPGME::Key.find(:public, key[:sha]).first
72
+
73
+ encrypted = crypto.encrypt TEXT[:plain], :recipients => real_key
74
+ assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
75
+
76
+ remove_key key
77
+ encrypted.seek 0
78
+ assert_raises GPGME::Error::DecryptFailed do
79
+ crypto.decrypt(encrypted)
80
+ end
81
+ import_key key
82
+ end
83
+
84
+ it "can also sign at the same time" do
85
+ crypto = GPGME::Crypto.new :always_trust => true
86
+ encrypted = crypto.encrypt TEXT[:plain], :sign => true
87
+ signatures = 0
88
+
89
+ crypto.verify(encrypted) do |signature|
90
+ assert_instance_of GPGME::Signature, signature
91
+ signatures += 1
92
+ end
93
+
94
+ assert_equal 1, signatures
95
+ end
96
+
97
+ it "can be signed by more than one person" do
98
+ crypto = GPGME::Crypto.new :always_trust => true
99
+ encrypted = crypto.encrypt TEXT[:plain], :sign => true, :signers => KEYS.map{|k| k[:sha]}
100
+ signatures = 0
101
+
102
+ crypto.verify(encrypted) do |signature|
103
+ assert_instance_of GPGME::Signature, signature
104
+ signatures += 1
105
+ end
106
+
107
+ assert_equal 4, signatures
108
+ end
109
+
110
+ it "outputs to a file if specified" do
111
+ crypto = GPGME::Crypto.new :always_trust => true
112
+ file = Tempfile.new "test"
113
+ crypto.encrypt TEXT[:plain], :output => file
114
+ file_contents = file.read
115
+ file.seek 0
116
+
117
+ refute_empty file_contents
118
+ assert_equal TEXT[:plain], crypto.decrypt(file).read
119
+ end
120
+
121
+ # TODO find how to test
122
+ # it "raises GPGME::Error::UnusablePublicKey"
123
+ # it "raises GPGME::Error::UnusableSecretKey"
124
+ end
125
+
126
+ describe "symmetric encryption/decryption" do
127
+ it "requires a password to encrypt" do
128
+ assert_raises GPGME::Error::BadPassphrase do
129
+ GPGME::Crypto.new.encrypt TEXT[:plain], :symmetric => true
130
+ end
131
+ end
132
+
133
+ it "requires a password to decrypt" do
134
+ crypto = GPGME::Crypto.new
135
+ encrypted_data = crypto.encrypt TEXT[:plain],
136
+ :symmetric => true, :password => "gpgme"
137
+
138
+ assert_raises GPGME::Error::BadPassphrase do
139
+ crypto.decrypt encrypted_data
140
+ end
141
+ end
142
+
143
+ it "can encrypt and decrypt with the same password" do
144
+ crypto = GPGME::Crypto.new :symmetric => true, :password => "gpgme"
145
+ encrypted_data = crypto.encrypt TEXT[:plain]
146
+ plain = crypto.decrypt encrypted_data
147
+
148
+ assert_equal "Hi there", plain.read
149
+ end
150
+
151
+ it "but breaks with different ones" do
152
+ crypto = GPGME::Crypto.new
153
+ encrypted_data = crypto.encrypt TEXT[:plain],
154
+ :symmetric => true, :password => "gpgme"
155
+
156
+ assert_raises GPGME::Error::DecryptFailed do
157
+ crypto.decrypt encrypted_data, :password => "wrong one"
158
+ end
159
+ end
160
+ end
161
+
162
+ describe :decrypt do
163
+ it "decrypts encrypted stuff" do
164
+ assert_equal TEXT[:plain], GPGME::Crypto.new.decrypt(TEXT[:encrypted]).read
165
+ end
166
+
167
+ it "will not get into the signatures block if there's none" do
168
+ GPGME::Crypto.new.decrypt(TEXT[:encrypted]) do |signature|
169
+ flunk "If I'm here means there was some signature"
170
+ end
171
+ pass
172
+ end
173
+
174
+ it "will get signature elements if the encrypted thing was signed" do
175
+ signatures = 0
176
+ GPGME::Crypto.new.decrypt(TEXT[:signed]) do |signature|
177
+ assert_instance_of GPGME::Signature, signature
178
+ signatures += 1
179
+ end
180
+ assert_equal 1, signatures
181
+ end
182
+
183
+ it "writes to the output if passed" do
184
+ buffer = GPGME::Data.new
185
+ GPGME::Crypto.new.decrypt(TEXT[:encrypted], :output => buffer)
186
+ assert_equal TEXT[:plain], buffer.read
187
+ end
188
+
189
+ # TODO find ways to test this
190
+ # it "raises UnsupportedAlgorithm"
191
+ # it "raises WrongKeyUsage"
192
+
193
+ it "raises DecryptFailed when the decrypting key isn't available" do
194
+ assert_raises GPGME::Error::DecryptFailed do
195
+ GPGME::Crypto.new.decrypt(TEXT[:unavailable])
196
+ end
197
+ end
198
+ end
199
+
200
+ describe :sign do
201
+ it "signs normal strings" do
202
+ crypto = GPGME::Crypto.new
203
+ signatures = 0
204
+ sign = crypto.sign "Hi there"
205
+
206
+ crypto.verify(sign) do |signature|
207
+ assert_instance_of GPGME::Signature, signature
208
+ assert signature.valid?
209
+ signatures += 1
210
+ end
211
+
212
+ assert_equal 1, signatures
213
+ end
214
+
215
+ # TODO Find how to import an expired public key
216
+ # it "raises an error if trying to sign with an expired key" do
217
+ # with_key EXPIRED_KEY do
218
+ # crypto = GPGME::Crypto.new
219
+ # assert_raises GPGME::Error::General do
220
+ # sign = crypto.sign "Hi there", :signer => EXPIRED_KEY[:sha]
221
+ # end
222
+ # end
223
+ # end
224
+
225
+ it "selects who to sign for" do
226
+ crypto = GPGME::Crypto.new
227
+ sign = crypto.sign "Hi there", :signer => KEYS.last[:sha]
228
+ key = GPGME::Key.get(KEYS.last[:sha])
229
+
230
+ signatures = 0
231
+
232
+ crypto.verify(sign) do |signature|
233
+ assert_instance_of GPGME::Signature, signature
234
+ assert_equal key, signature.key
235
+ signatures += 1
236
+ end
237
+
238
+ assert_equal 1, signatures
239
+ end
240
+
241
+ end
242
+ end