gpgme 1.0.8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/examples/genkey.rb +1 -1
  2. data/examples/keylist.rb +2 -1
  3. data/examples/roundtrip.rb +7 -4
  4. data/examples/sign.rb +5 -3
  5. data/examples/verify.rb +4 -2
  6. data/ext/gpgme/extconf.rb +58 -0
  7. data/ext/gpgme/gpgme-1.3.1.tar.bz2 +0 -0
  8. data/{gpgme_n.c → ext/gpgme/gpgme_n.c} +8 -8
  9. data/ext/gpgme/libassuan-2.0.2.tar.bz2 +0 -0
  10. data/ext/gpgme/libgpg-error-1.10.tar.bz2 +0 -0
  11. data/lib/gpgme.rb +88 -1541
  12. data/lib/gpgme/compat.rb +2 -0
  13. data/lib/gpgme/constants.rb +23 -0
  14. data/lib/gpgme/crypto.rb +357 -0
  15. data/lib/gpgme/ctx.rb +462 -0
  16. data/lib/gpgme/data.rb +177 -0
  17. data/lib/gpgme/engine.rb +76 -0
  18. data/lib/gpgme/error.rb +66 -0
  19. data/lib/gpgme/io_callbacks.rb +21 -0
  20. data/lib/gpgme/key.rb +242 -0
  21. data/lib/gpgme/key_common.rb +43 -0
  22. data/lib/gpgme/key_sig.rb +35 -0
  23. data/lib/gpgme/misc.rb +66 -0
  24. data/lib/gpgme/signature.rb +85 -0
  25. data/lib/gpgme/sub_key.rb +58 -0
  26. data/lib/gpgme/user_id.rb +20 -0
  27. data/lib/gpgme/version.rb +3 -0
  28. data/test/crypto_test.rb +242 -0
  29. data/test/ctx_test.rb +426 -0
  30. data/test/data_test.rb +116 -0
  31. data/test/files/testkey_pub.gpg +52 -0
  32. data/test/files/testkey_sec.gpg +54 -0
  33. data/test/gpgme_test.rb +12 -0
  34. data/test/key_test.rb +201 -0
  35. data/test/signature_test.rb +48 -0
  36. data/test/sub_key_test.rb +45 -0
  37. data/test/support/resources.rb +516 -0
  38. data/test/test_helper.rb +83 -0
  39. metadata +144 -65
  40. data.tar.gz.sig +0 -3
  41. data/COPYING +0 -340
  42. data/COPYING.LESSER +0 -510
  43. data/Makefile +0 -172
  44. data/Manifest.txt +0 -18
  45. data/README +0 -86
  46. data/Rakefile +0 -17
  47. data/THANKS +0 -15
  48. data/extconf.rb +0 -26
  49. metadata.gz.sig +0 -0
@@ -0,0 +1,43 @@
1
+ module GPGME
2
+ module KeyCommon
3
+
4
+ ##
5
+ # Returns nil if the trust is valid.
6
+ # Returns one of +:revoked+, +:expired+, +:disabled+, +:invalid+
7
+ def trust
8
+ return :revoked if @revoked == 1
9
+ return :expired if @expired == 1
10
+ return :disabled if @disabled == 1
11
+ return :invalid if @invalid == 1
12
+ end
13
+
14
+ ##
15
+ # Array of capabilities for this key. It can contain any combination of
16
+ # +:encrypt+, +:sign+, +:certify+ or +:authenticate+
17
+ def capability
18
+ caps = []
19
+ caps << :encrypt if @can_encrypt
20
+ caps << :sign if @can_sign
21
+ caps << :certify if @can_certify
22
+ caps << :authenticate if @can_authenticate
23
+ caps
24
+ end
25
+
26
+ ##
27
+ # Checks if the key is capable of all of these actions. If empty array
28
+ # is passed then will return true.
29
+ #
30
+ # Returns false if the keys trust has been invalidated.
31
+ def usable_for?(purposes)
32
+ unless purposes.kind_of? Array
33
+ purposes = [purposes]
34
+ end
35
+ return false if [:revoked, :expired, :disabled, :invalid].include? trust
36
+ return (purposes - capability).empty?
37
+ end
38
+
39
+ def secret?
40
+ @secret == 1
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ module GPGME
2
+ class KeySig
3
+ private_class_method :new
4
+
5
+ attr_reader :pubkey_algo, :keyid
6
+
7
+ def revoked?
8
+ @revoked == 1
9
+ end
10
+
11
+ def expired?
12
+ @expired == 1
13
+ end
14
+
15
+ def invalid?
16
+ @invalid == 1
17
+ end
18
+
19
+ def exportable?
20
+ @exportable == 1
21
+ end
22
+
23
+ def timestamp
24
+ Time.at(@timestamp)
25
+ end
26
+
27
+ def expires
28
+ Time.at(@expires)
29
+ end
30
+
31
+ def inspect
32
+ "#<#{self.class} #{keyid} timestamp=#{timestamp}, expires=#{expires}>"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,66 @@
1
+ module GPGME
2
+ class EngineInfo
3
+ private_class_method :new
4
+
5
+ attr_reader :protocol, :file_name, :version, :req_version, :home_dir
6
+ alias required_version req_version
7
+ end
8
+
9
+ class VerifyResult
10
+ private_class_method :new
11
+
12
+ attr_reader :signatures
13
+ end
14
+
15
+ class DecryptResult
16
+ private_class_method :new
17
+
18
+ attr_reader :unsupported_algorithm, :wrong_key_usage
19
+ end
20
+
21
+ class SignResult
22
+ private_class_method :new
23
+
24
+ attr_reader :invalid_signers, :signatures
25
+ end
26
+
27
+ class EncryptResult
28
+ private_class_method :new
29
+
30
+ attr_reader :invalid_recipients
31
+ end
32
+
33
+ class InvalidKey
34
+ private_class_method :new
35
+
36
+ attr_reader :fpr, :reason
37
+ alias fingerprint fpr
38
+ end
39
+
40
+ class NewSignature
41
+ private_class_method :new
42
+
43
+ attr_reader :type, :pubkey_algo, :hash_algo, :sig_class, :fpr
44
+ alias fingerprint fpr
45
+
46
+ def timestamp
47
+ Time.at(@timestamp)
48
+ end
49
+ end
50
+
51
+ class ImportStatus
52
+ private_class_method :new
53
+
54
+ attr_reader :fpr, :result, :status
55
+ alias fingerprint fpr
56
+ end
57
+
58
+ class ImportResult
59
+ private_class_method :new
60
+
61
+ attr_reader :considered, :no_user_id, :imported, :imported_rsa, :unchanged
62
+ attr_reader :new_user_ids, :new_sub_keys, :new_signatures, :new_revocations
63
+ attr_reader :secret_read, :secret_imported, :secret_unchanged
64
+ attr_reader :not_imported, :imports
65
+ end
66
+ end
@@ -0,0 +1,85 @@
1
+ module GPGME
2
+ class Signature
3
+ private_class_method :new
4
+
5
+ attr_reader :summary, :fpr, :status, :notations, :wrong_key_usage
6
+ attr_reader :validity, :validity_reason
7
+ attr_reader :pka_trust, :pka_address
8
+ alias fingerprint fpr
9
+
10
+ ##
11
+ # Returns true if the signature is correct
12
+ def valid?
13
+ status_code == GPGME::GPG_ERR_NO_ERROR
14
+ end
15
+
16
+ def expired_signature?
17
+ status_code == GPGME::GPG_ERR_SIG_EXPIRED
18
+ end
19
+
20
+ def expired_key?
21
+ status_code == GPGME::GPG_ERR_KEY_EXPIRED
22
+ end
23
+
24
+ def revoked_key?
25
+ status_code == GPGME::GPG_ERR_CERT_REVOKED
26
+ end
27
+
28
+ def bad?
29
+ status_code == GPGME::GPG_ERR_BAD_SIGNATURE
30
+ end
31
+
32
+ def no_key?
33
+ status_code == GPGME::GPG_ERR_NO_PUBKEY
34
+ end
35
+
36
+ def status_code
37
+ GPGME::gpgme_err_code(status)
38
+ end
39
+
40
+ def from
41
+ @from ||= begin
42
+ Ctx.new do |ctx|
43
+ if from_key = ctx.get_key(fingerprint)
44
+ "#{from_key.subkeys[0].keyid} #{from_key.uids[0].uid}"
45
+ else
46
+ fingerprint
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ def key
53
+ @key ||= begin
54
+ Ctx.new do |ctx|
55
+ @key = ctx.get_key(fingerprint)
56
+ end
57
+ end
58
+ end
59
+
60
+ def timestamp
61
+ Time.at(@timestamp)
62
+ end
63
+
64
+ def exp_timestamp
65
+ Time.at(@exp_timestamp)
66
+ end
67
+
68
+ def to_s
69
+ case status_code
70
+ when GPGME::GPG_ERR_NO_ERROR
71
+ "Good signature from #{from}"
72
+ when GPGME::GPG_ERR_SIG_EXPIRED
73
+ "Expired signature from #{from}"
74
+ when GPGME::GPG_ERR_KEY_EXPIRED
75
+ "Signature made from expired key #{from}"
76
+ when GPGME::GPG_ERR_CERT_REVOKED
77
+ "Signature made from revoked key #{from}"
78
+ when GPGME::GPG_ERR_BAD_SIGNATURE
79
+ "Bad signature from #{from}"
80
+ when GPGME::GPG_ERR_NO_PUBKEY
81
+ "No public key for #{from}"
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,58 @@
1
+ module GPGME
2
+ class SubKey
3
+ private_class_method :new
4
+
5
+ attr_reader :pubkey_algo, :length, :keyid, :fpr
6
+ alias fingerprint fpr
7
+
8
+ include KeyCommon
9
+
10
+ def timestamp
11
+ Time.at(@timestamp)
12
+ end
13
+
14
+ def expires
15
+ Time.at(@expires)
16
+ end
17
+
18
+ def expired
19
+ return false if @expires == 0
20
+ @expires < Time.now.to_i
21
+ end
22
+
23
+ def sha
24
+ (@fingerprint || @keyid)[-8 .. -1]
25
+ end
26
+
27
+ PUBKEY_ALGO_LETTERS = {
28
+ PK_RSA => "R",
29
+ PK_ELG_E => "g",
30
+ PK_ELG => "G",
31
+ PK_DSA => "D"
32
+ }
33
+
34
+ def pubkey_algo_letter
35
+ PUBKEY_ALGO_LETTERS[@pubkey_algo] || "?"
36
+ end
37
+
38
+ def inspect
39
+ sprintf("#<#{self.class} %s %4d%s/%s %s trust=%s, capability=%s>",
40
+ secret? ? 'ssc' : 'sub',
41
+ length,
42
+ pubkey_algo_letter,
43
+ (@fingerprint || @keyid)[-8 .. -1],
44
+ timestamp.strftime('%Y-%m-%d'),
45
+ trust.inspect,
46
+ capability.inspect)
47
+ end
48
+
49
+ def to_s
50
+ sprintf("%s %4d%s/%s %s\n",
51
+ secret? ? 'ssc' : 'sub',
52
+ length,
53
+ pubkey_algo_letter,
54
+ (@fingerprint || @keyid)[-8 .. -1],
55
+ timestamp.strftime('%Y-%m-%d'))
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,20 @@
1
+ module GPGME
2
+ class UserID
3
+ private_class_method :new
4
+
5
+ attr_reader :validity, :uid, :name, :comment, :email, :signatures
6
+
7
+ def revoked?
8
+ @revoked == 1
9
+ end
10
+
11
+ def invalid?
12
+ @invalid == 1
13
+ end
14
+
15
+ def inspect
16
+ "#<#{self.class} #{name} <#{email}> \
17
+ validity=#{VALIDITY_NAMES[validity]}, signatures=#{signatures.inspect}>"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module GPGME
2
+ VERSION = "1.0.8"
3
+ 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