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
@@ -1,5 +1,7 @@
1
1
  require 'gpgme'
2
2
 
3
+ # TODO: Find why is this needed. I guess the name compat means it's just
4
+ # backwards compatibility. Consider removing?
3
5
  module GPGME
4
6
  GpgmeError = Error
5
7
  GpgmeData = Data
@@ -1,4 +1,5 @@
1
1
  module GPGME
2
+
2
3
  ATTR_ALGO = GPGME_ATTR_ALGO
3
4
  ATTR_CAN_CERTIFY = GPGME_ATTR_CAN_CERTIFY
4
5
  ATTR_CAN_ENCRYPT = GPGME_ATTR_CAN_ENCRYPT
@@ -161,4 +162,26 @@ module GPGME
161
162
  VALIDITY_ULTIMATE = GPGME_VALIDITY_ULTIMATE
162
163
  VALIDITY_UNDEFINED = GPGME_VALIDITY_UNDEFINED
163
164
  VALIDITY_UNKNOWN = GPGME_VALIDITY_UNKNOWN
165
+
166
+ PROTOCOL_NAMES = {
167
+ PROTOCOL_OpenPGP => :OpenPGP,
168
+ PROTOCOL_CMS => :CMS
169
+ }
170
+
171
+ KEYLIST_MODE_NAMES = {
172
+ KEYLIST_MODE_LOCAL => :local,
173
+ KEYLIST_MODE_EXTERN => :extern,
174
+ KEYLIST_MODE_SIGS => :sigs,
175
+ KEYLIST_MODE_VALIDATE => :validate
176
+ }
177
+
178
+ VALIDITY_NAMES = {
179
+ VALIDITY_UNKNOWN => :unknown,
180
+ VALIDITY_UNDEFINED => :undefined,
181
+ VALIDITY_NEVER => :never,
182
+ VALIDITY_MARGINAL => :marginal,
183
+ VALIDITY_FULL => :full,
184
+ VALIDITY_ULTIMATE => :ultimate
185
+ }
186
+
164
187
  end
@@ -0,0 +1,357 @@
1
+ module GPGME
2
+
3
+ ##
4
+ # Different, independent methods providing the simplest possible API to
5
+ # execute crypto operations via GPG. All methods accept as options the same
6
+ # common options as {GPGME::Ctx.new}. Read the documentation for that class to
7
+ # know how to customize things further (like output stuff in ASCII armored
8
+ # format, for example).
9
+ #
10
+ # @example
11
+ # crypto = GPGME::Crypto.new :armor => true
12
+ # encrypted = crypto.encrypt 'Plain text'
13
+ #
14
+ class Crypto
15
+
16
+ attr_reader :default_options
17
+
18
+ def initialize(options = {})
19
+ @default_options = options
20
+ end
21
+
22
+ ##
23
+ # Encrypts an element
24
+ #
25
+ # crypto.encrypt something, options
26
+ #
27
+ # Will return a {GPGME::Data} element which can then be read.
28
+ #
29
+ # Must have some key imported, look for {GPGME::Key.import} to know how
30
+ # to import one, or the gpg documentation to know how to create one
31
+ #
32
+ # @param plain
33
+ # Must be something that can be converted into a {GPGME::Data} object, or
34
+ # a {GPGME::Data} object itself.
35
+ #
36
+ # @param [Hash] options
37
+ # The optional parameters are as follows:
38
+ # * +:recipients+ for which recipient do you want to encrypt this file. It
39
+ # will pick the first one available if none specified. Can be an array of
40
+ # identifiers or just one (a string).
41
+ # * +:symmetric+ if set to true, will ignore +:recipients+, and will perform
42
+ # a symmetric encryption. Must provide a password via the +:password+
43
+ # option.
44
+ # * +:always_trust+ if set to true specifies all the recipients to be
45
+ # trusted, thus not requiring confirmation.
46
+ # * +:sign+ if set to true, performs a combined sign and encrypt operation.
47
+ # * +:signers+ if +:sign+ specified to true, a list of additional possible
48
+ # signers. Must be an array of sign identifiers.
49
+ # * +:output+ if specified, it will write the output into it. It will be
50
+ # converted to a {GPGME::Data} object, so it could be a file for example.
51
+ # * Any other option accepted by {GPGME::Ctx.new}
52
+ #
53
+ # @return [GPGME::Data] a {GPGME::Data} object that can be read.
54
+ #
55
+ # @example returns a {GPGME::Data} that can be later encrypted
56
+ # encrypted = crypto.encrypt "Hello world!"
57
+ # encrypted.read # => Encrypted stuff
58
+ #
59
+ # @example to be decrypted by someone@example.com.
60
+ # crypto.encrypt "Hello", :recipients => "someone@example.com"
61
+ #
62
+ # @example If I didn't trust any of my keys by default
63
+ # crypto.encrypt "Hello" # => GPGME::Error::General
64
+ # crypto.encrypt "Hello", :always_trust => true # => Will work fine
65
+ #
66
+ # @example encrypted string that can be decrypted and/or *verified*
67
+ # crypto.encrypt "Hello", :sign => true
68
+ #
69
+ # @example multiple signers
70
+ # crypto.encrypt "Hello", :sign => true, :signers => "extra@example.com"
71
+ #
72
+ # @example writing to a file instead
73
+ # file = File.open("signed.sec","w+")
74
+ # crypto.encrypt "Hello", :output => file # output written to signed.sec
75
+ #
76
+ # @raise [GPGME::Error::General] when trying to encrypt with a key that is
77
+ # not trusted, and +:always_trust+ wasn't specified
78
+ #
79
+ def encrypt(plain, options = {})
80
+ options = @default_options.merge options
81
+
82
+ plain_data = Data.new(plain)
83
+ cipher_data = Data.new(options[:output])
84
+ keys = Key.find(:public, options[:recipients])
85
+ keys = nil if options[:symmetric]
86
+
87
+ flags = 0
88
+ flags |= GPGME::ENCRYPT_ALWAYS_TRUST if options[:always_trust]
89
+
90
+ GPGME::Ctx.new(options) do |ctx|
91
+ begin
92
+ if options[:sign]
93
+ if options[:signers]
94
+ signers = Key.find(:public, options[:signers], :sign)
95
+ ctx.add_signer(*signers)
96
+ end
97
+ ctx.encrypt_sign(keys, plain_data, cipher_data, flags)
98
+ else
99
+ ctx.encrypt(keys, plain_data, cipher_data, flags)
100
+ end
101
+ rescue GPGME::Error::UnusablePublicKey => exc
102
+ exc.keys = ctx.encrypt_result.invalid_recipients
103
+ raise exc
104
+ rescue GPGME::Error::UnusableSecretKey => exc
105
+ exc.keys = ctx.sign_result.invalid_signers
106
+ raise exc
107
+ end
108
+ end
109
+
110
+ cipher_data.seek(0)
111
+ cipher_data
112
+ end
113
+
114
+ ##
115
+ # Decrypts a previously encrypted element
116
+ #
117
+ # crypto.decrypt cipher, options, &block
118
+ #
119
+ # Must have the appropiate key to be able to decrypt, of course. Returns
120
+ # a {GPGME::Data} object which can then be read.
121
+ #
122
+ # @param cipher
123
+ # Must be something that can be converted into a {GPGME::Data} object,
124
+ # or a {GPGME::Data} object itself. It is the element that will be
125
+ # decrypted.
126
+ #
127
+ # @param [Hash] options
128
+ # The optional parameters:
129
+ # * +:output+ if specified, it will write the output into it. It will
130
+ # me converted to a {GPGME::Data} object, so it can also be a file,
131
+ # for example.
132
+ # * If the file was encrypted with symmentric encryption, must provide
133
+ # a :password option.
134
+ # * Any other option accepted by {GPGME::Ctx.new}
135
+ #
136
+ # @param &block
137
+ # In the block all the signatures are yielded, so one could verify them.
138
+ # See examples.
139
+ #
140
+ # @return [GPGME::Data] a {GPGME::Data} that can be read.
141
+ #
142
+ # @example Simple decrypt
143
+ # crypto.decrypt encrypted_data
144
+ #
145
+ # @example symmetric encryption, or passwored key
146
+ # crypto.decrypt encrypted_data, :password => "gpgme"
147
+ #
148
+ # @example Output to file
149
+ # file = File.open("decrypted.txt", "w+")
150
+ # crypto.decrypt encrypted_data, :output => file
151
+ #
152
+ # @example Verifying signatures
153
+ # crypto.decrypt encrypted_data do |signature|
154
+ # raise "Signature could not be verified" unless signature.valid?
155
+ # end
156
+ #
157
+ # @raise [GPGME::Error::UnsupportedAlgorithm] when the cipher was encrypted
158
+ # using an algorithm that's not supported currently.
159
+ #
160
+ # @raise [GPGME::Error::WrongKeyUsage] TODO Don't know when
161
+ #
162
+ # @raise [GPGME::Error::DecryptFailed] when the cipher was encrypted
163
+ # for a key that's not available currently.
164
+ def decrypt(cipher, options = {})
165
+ options = @default_options.merge options
166
+
167
+ plain_data = Data.new(options[:output])
168
+ cipher_data = Data.new(cipher)
169
+
170
+ GPGME::Ctx.new(options) do |ctx|
171
+ begin
172
+ ctx.decrypt_verify(cipher_data, plain_data)
173
+ rescue GPGME::Error::UnsupportedAlgorithm => exc
174
+ exc.algorithm = ctx.decrypt_result.unsupported_algorithm
175
+ raise exc
176
+ rescue GPGME::Error::WrongKeyUsage => exc
177
+ exc.key_usage = ctx.decrypt_result.wrong_key_usage
178
+ raise exc
179
+ end
180
+
181
+ verify_result = ctx.verify_result
182
+ if verify_result && block_given?
183
+ verify_result.signatures.each do |signature|
184
+ yield signature
185
+ end
186
+ end
187
+
188
+ end
189
+
190
+ plain_data.seek(0)
191
+ plain_data
192
+ end
193
+
194
+ ##
195
+ # Creates a signature of a text
196
+ #
197
+ # crypto.sign text, options
198
+ #
199
+ # Must have the appropiate key to be able to decrypt, of course. Returns
200
+ # a {GPGME::Data} object which can then be read.
201
+ #
202
+ # @param text
203
+ # The object that will be signed. Must be something that can be converted
204
+ # to {GPGME::Data}.
205
+ #
206
+ # @param [Hash] options
207
+ # Optional parameters.
208
+ # * +:signer+ sign identifier to sign the text with. Will use the first
209
+ # key it finds if none specified.
210
+ # * +:output+ if specified, it will write the output into it. It will be
211
+ # converted to a {GPGME::Data} object, so it could be a file for example.
212
+ # * +:mode+ Desired type of signature. Options are:
213
+ # - +GPGME::SIG_MODE_NORMAL+ for a normal signature. The default one if
214
+ # not specified.
215
+ # - +GPGME::SIG_MODE_DETACH+ for a detached signature
216
+ # - +GPGME::SIG_MODE_CLEAR+ for a cleartext signature
217
+ # * Any other option accepted by {GPGME::Ctx.new}
218
+ #
219
+ # @return [GPGME::Data] a {GPGME::Data} that can be read.
220
+ #
221
+ # @example normal sign
222
+ # crypto.sign "Hi there"
223
+ #
224
+ # @example outputing to a file
225
+ # file = File.open("text.sign", "w+")
226
+ # crypto.sign "Hi there", :options => file
227
+ #
228
+ # @example doing a detached signature
229
+ # crypto.sign "Hi there", :mode => GPGME::SIG_MODE_DETACH
230
+ #
231
+ # @example specifying the signer
232
+ # crypto.sign "Hi there", :signer => "mrsimo@example.com"
233
+ #
234
+ # @raise [GPGME::Error::UnusableSecretKey] TODO don't know when
235
+ def sign(text, options = {})
236
+ options = @default_options.merge options
237
+
238
+ plain = Data.new(text)
239
+ output = Data.new(options[:output])
240
+ mode = options[:mode] || GPGME::SIG_MODE_NORMAL
241
+
242
+ GPGME::Ctx.new(options) do |ctx|
243
+ if options[:signer]
244
+ signers = Key.find(:secret, options[:signer], :sign)
245
+ ctx.add_signer(*signers)
246
+ end
247
+
248
+ begin
249
+ ctx.sign(plain, output, mode)
250
+ rescue GPGME::Error::UnusableSecretKey => exc
251
+ exc.keys = ctx.sign_result.invalid_signers
252
+ raise exc
253
+ end
254
+ end
255
+
256
+ output.seek(0)
257
+ output
258
+ end
259
+
260
+ # Verifies a previously signed element
261
+ #
262
+ # crypto.verify sig, options, &block
263
+ #
264
+ # Must have the proper keys available.
265
+ #
266
+ # @param sig
267
+ # The signature itself. Must be possible to convert into a {GPGME::Data}
268
+ # object, so can be a file.
269
+ #
270
+ # @param [Hash] options
271
+ # * +:signed_text+ if the sign is detached, then must be the plain text
272
+ # for which the signature was created.
273
+ # * +:output+ where to store the result of the signature. Will be
274
+ # converted to a {GPGME::Data} object.
275
+ # * Any other option accepted by {GPGME::Ctx.new}
276
+ #
277
+ # @param &block
278
+ # In the block all the signatures are yielded, so one could verify them.
279
+ # See examples.
280
+ #
281
+ # @return [GPGME::Data] unless the sign is detached, the {GPGME::Data}
282
+ # object with the plain text. If the sign is detached, will return nil.
283
+ #
284
+ # @example simple verification
285
+ # sign = crypto.sign("Hi there")
286
+ # data = crypto.verify(sign) { |signature| signature.valid? }
287
+ # data.read # => "Hi there"
288
+ #
289
+ # @example saving output to file
290
+ # sign = crypto.sign("Hi there")
291
+ # out = File.open("test.asc", "w+")
292
+ # crypto.verify(sign, :output => out) {|signature| signature.valid?}
293
+ # out.read # => "Hi there"
294
+ #
295
+ # @example verifying a detached signature
296
+ # sign = crypto.detach_sign("Hi there")
297
+ # # Will fail
298
+ # crypto.verify(sign) { |signature| signature.valid? }
299
+ # # Will succeed
300
+ # crypto.verify(sign, :signed_text => "hi there") do |signature|
301
+ # signature.valid?
302
+ # end
303
+ #
304
+ def verify(sig, options = {})
305
+ options = @default_options.merge options
306
+
307
+ sig = Data.new(sig)
308
+ signed_text = Data.new(options[:signed_text])
309
+ output = Data.new(options[:output]) unless options[:signed_text]
310
+
311
+ GPGME::Ctx.new(options) do |ctx|
312
+ ctx.verify(sig, signed_text, output)
313
+ ctx.verify_result.signatures.each do |signature|
314
+ yield signature
315
+ end
316
+ end
317
+
318
+ if output
319
+ output.seek(0)
320
+ output
321
+ end
322
+ end
323
+
324
+ # Clearsigns an element
325
+ #
326
+ # crypto.clearsign text, options
327
+ #
328
+ # Same functionality of {.sign} only doing clearsigns by default.
329
+ #
330
+ def clearsign(text, options = {})
331
+ sign text, options.merge(:mode => GPGME::SIG_MODE_CLEAR)
332
+ end
333
+
334
+ # Creates a detached signature of an element
335
+ #
336
+ # crypto.detach_sign text, options
337
+ #
338
+ # Same functionality of {.sign} only doing detached signs by default.
339
+ #
340
+ def detach_sign(text, options = {})
341
+ sign text, options.merge(:mode => GPGME::SIG_MODE_DETACH)
342
+ end
343
+
344
+ ##
345
+ # Allows calling of methods directly in the module without the need to
346
+ # create a new instance.
347
+ def self.method_missing(method, *args, &block)
348
+ if GPGME::Crypto.instance_methods(false).include?(method)
349
+ crypto = GPGME::Crypto.new
350
+ crypto.send method, *args, &block
351
+ else
352
+ super
353
+ end
354
+ end
355
+
356
+ end # module Crypto
357
+ end # module GPGME
@@ -0,0 +1,462 @@
1
+ module GPGME
2
+
3
+ ##
4
+ # A context within which all cryptographic operations are performed.
5
+ #
6
+ # More operations can be done which are not available in the higher level
7
+ # API. Note how to create a new instance of this class in {GPGME::Ctx.new}.
8
+ #
9
+ class Ctx
10
+
11
+ ##
12
+ # Create a new instance from the given +options+. Must be released either
13
+ # executing the operations inside a block, or executing {GPGME::Ctx#release}
14
+ # afterwards.
15
+ #
16
+ # @param [Hash] options
17
+ # The optional parameters are as follows:
18
+ # * +:protocol+ Either +PROTOCOL_OpenPGP+ or +PROTOCOL_CMS+.
19
+ # * +:armor+ will return ASCII armored outputs if specified true.
20
+ # * +:textmode+ if +true+, inform the recipient that the input is text.
21
+ # * +:keylist_mode+ One of: +KEYLIST_MODE_LOCAL+, +KEYLIST_MODE_EXTERN+,
22
+ # +KEYLIST_MODE_SIGS+ or +KEYLIST_MODE_VALIDATE+.
23
+ # * +:password+ password of the passphrased password being used.
24
+ # * +:passphrase_callback+ A callback function. See {#set_passphrase_callback}.
25
+ # * +:passphrase_callback_value+ An object passed to passphrase_callback.
26
+ # * +:progress_callback+ A callback function. See {#set_progress_callback}.
27
+ # * +:progress_callback_value+ An object passed to progress_callback.
28
+ #
29
+ # @example
30
+ # ctx = GPGME::Ctx.new
31
+ # # operate on ctx
32
+ # ctx.release
33
+ #
34
+ # @example
35
+ # GPGME::Ctx.new do |ctx|
36
+ # # operate on ctx
37
+ # end
38
+ #
39
+ def self.new(options = {})
40
+ rctx = []
41
+ err = GPGME::gpgme_new(rctx)
42
+ exc = GPGME::error_to_exception(err)
43
+ raise exc if exc
44
+ ctx = rctx[0]
45
+
46
+ ctx.protocol = options[:protocol] if options[:protocol]
47
+ ctx.armor = options[:armor] if options[:armor]
48
+ ctx.textmode = options[:textmode] if options[:textmode]
49
+ ctx.keylist_mode = options[:keylist_mode] if options[:keylist_mode]
50
+
51
+ if options[:password]
52
+ ctx.set_passphrase_callback GPGME::Ctx.method(:pass_function),
53
+ options[:password]
54
+ else
55
+ if options[:passphrase_callback]
56
+ ctx.set_passphrase_callback options[:passphrase_callback],
57
+ options[:passphrase_callback_value]
58
+ end
59
+ end
60
+ if options[:progress_callback]
61
+ ctx.set_progress_callback options[:progress_callback],
62
+ options[:progress_callback_value]
63
+ end
64
+
65
+ if block_given?
66
+ begin
67
+ yield ctx
68
+ ensure
69
+ GPGME::gpgme_release(ctx)
70
+ end
71
+ else
72
+ ctx
73
+ end
74
+ end
75
+
76
+
77
+ ##
78
+ # Releases the Ctx instance. Must be called if it was initialized without
79
+ # a block.
80
+ #
81
+ # @example
82
+ # ctx = GPGME::Ctx.new
83
+ # # operate on ctx
84
+ # ctx.release
85
+ #
86
+ def release
87
+ GPGME::gpgme_release(self)
88
+ end
89
+
90
+ ##
91
+ # Getters and setters
92
+ ##
93
+
94
+ # Set the +protocol+ used within this context. See {GPGME::Ctx.new} for
95
+ # possible values.
96
+ def protocol=(proto)
97
+ err = GPGME::gpgme_set_protocol(self, proto)
98
+ exc = GPGME::error_to_exception(err)
99
+ raise exc if exc
100
+ proto
101
+ end
102
+
103
+ # Return the +protocol+ used within this context.
104
+ def protocol
105
+ GPGME::gpgme_get_protocol(self)
106
+ end
107
+
108
+ # Tell whether the output should be ASCII armored.
109
+ def armor=(yes)
110
+ GPGME::gpgme_set_armor(self, yes ? 1 : 0)
111
+ yes
112
+ end
113
+
114
+ # Return true if the output is ASCII armored.
115
+ def armor
116
+ GPGME::gpgme_get_armor(self) == 1 ? true : false
117
+ end
118
+
119
+ # Tell whether canonical text mode should be used.
120
+ def textmode=(yes)
121
+ GPGME::gpgme_set_textmode(self, yes ? 1 : 0)
122
+ yes
123
+ end
124
+
125
+ # Return true if canonical text mode is enabled.
126
+ def textmode
127
+ GPGME::gpgme_get_textmode(self) == 1 ? true : false
128
+ end
129
+
130
+ # Change the default behaviour of the key listing functions.
131
+ def keylist_mode=(mode)
132
+ GPGME::gpgme_set_keylist_mode(self, mode)
133
+ mode
134
+ end
135
+
136
+ # Return the current key listing mode.
137
+ def keylist_mode
138
+ GPGME::gpgme_get_keylist_mode(self)
139
+ end
140
+
141
+ ##
142
+ # Passphrase and progress callbacks
143
+ ##
144
+
145
+ # Set the passphrase callback with given hook value.
146
+ # +passfunc+ should respond to +call+ with 5 arguments.
147
+ #
148
+ # * +obj+ the parameter +:passphrase_callback_value+ passed when creating
149
+ # the {GPGME::Ctx} object.
150
+ # * +uid_hint+ hint as to what key are we asking the password for. Ex:
151
+ #
152
+ # +CFB3294A50C2CFD7 Albert Llop <mrsimo@example.com>+
153
+ #
154
+ # * +passphrase_info+
155
+ # * +prev_was_bad+ 0 if it's the first time the password is being asked,
156
+ # 1 otherwise.
157
+ # * +fd+ file descriptor where the password must be written too.
158
+ #
159
+ # Expects a Method object which can be obtained by the +method+ method
160
+ # (really..).
161
+ #
162
+ # ctx.set_passphrase_callback(MyModule.method(:passfunc))
163
+ #
164
+ # @example this method will simply return +maria+ as password.
165
+ # def pass_function(obj, uid_hint, passphrase_info, prev_was_bad, fd)
166
+ # io = IO.for_fd(fd, 'w')
167
+ # io.puts "maria"
168
+ # io.flush
169
+ # end
170
+ #
171
+ # @example this will interactively ask for the password
172
+ # def passfunc(obj, uid_hint, passphrase_info, prev_was_bad, fd)
173
+ # $stderr.write("Passphrase for #{uid_hint}: ")
174
+ # $stderr.flush
175
+ # begin
176
+ # system('stty -echo')
177
+ # io = IO.for_fd(fd, 'w')
178
+ # io.puts(gets)
179
+ # io.flush
180
+ # ensure
181
+ # (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
182
+ # system('stty echo')
183
+ # end
184
+ # $stderr.puts
185
+ # end
186
+ #
187
+ def set_passphrase_callback(passfunc, hook_value = nil)
188
+ GPGME::gpgme_set_passphrase_cb(self, passfunc, hook_value)
189
+ end
190
+ alias set_passphrase_cb set_passphrase_callback
191
+
192
+ # Set the progress callback with given hook value.
193
+ # <i>progfunc</i> should respond to <code>call</code> with 5 arguments.
194
+ #
195
+ # def progfunc(hook, what, type, current, total)
196
+ # $stderr.write("#{what}: #{current}/#{total}\r")
197
+ # $stderr.flush
198
+ # end
199
+ #
200
+ # ctx.set_progress_callback(method(:progfunc))
201
+ #
202
+ def set_progress_callback(progfunc, hook_value = nil)
203
+ GPGME::gpgme_set_progress_cb(self, progfunc, hook_value)
204
+ end
205
+ alias set_progress_cb set_progress_callback
206
+
207
+ ##
208
+ # Searching and iterating through keys. Used by {GPGME::Key.find}
209
+ ##
210
+
211
+ # Initiate a key listing operation for given pattern. If +pattern+ is
212
+ # +nil+, all available keys are returned. If +secret_only<+ is +true+,
213
+ # only secret keys are returned.
214
+ #
215
+ # Used by {GPGME::Ctx#each_key}
216
+ def keylist_start(pattern = nil, secret_only = false)
217
+ err = GPGME::gpgme_op_keylist_start(self, pattern, secret_only ? 1 : 0)
218
+ exc = GPGME::error_to_exception(err)
219
+ raise exc if exc
220
+ end
221
+
222
+ # Advance to the next key in the key listing operation.
223
+ #
224
+ # Used by {GPGME::Ctx#each_key}
225
+ def keylist_next
226
+ rkey = []
227
+ err = GPGME::gpgme_op_keylist_next(self, rkey)
228
+ exc = GPGME::error_to_exception(err)
229
+ raise exc if exc
230
+ rkey[0]
231
+ end
232
+
233
+ # End a pending key list operation.
234
+ #
235
+ # Used by {GPGME::Ctx#each_key}
236
+ def keylist_end
237
+ err = GPGME::gpgme_op_keylist_end(self)
238
+ exc = GPGME::error_to_exception(err)
239
+ raise exc if exc
240
+ end
241
+
242
+ # Convenient method to iterate over keys.
243
+ #
244
+ # If +pattern+ is +nil+, all available keys are returned. If +secret_only+
245
+ # is +true+, only secret keys are returned.
246
+ #
247
+ # See {GPGME::Key.find} for an example of how to use, or for an easier way
248
+ # to use.
249
+ def each_key(pattern = nil, secret_only = false, &block)
250
+ keylist_start(pattern, secret_only)
251
+ begin
252
+ loop { yield keylist_next }
253
+ rescue EOFError
254
+ # The last key in the list has already been returned.
255
+ ensure
256
+ keylist_end
257
+ end
258
+ end
259
+ alias each_keys each_key
260
+
261
+ # Returns the keys that match the +pattern+, or all if +pattern+ is nil.
262
+ # Returns only secret keys if +secret_only+ is true.
263
+ def keys(pattern = nil, secret_only = nil)
264
+ keys = []
265
+ each_key(pattern, secret_only) do |key|
266
+ keys << key
267
+ end
268
+ keys
269
+ end
270
+
271
+ # Get the key with the +fingerprint+.
272
+ # If +secret+ is +true+, secret key is returned.
273
+ def get_key(fingerprint, secret = false)
274
+ rkey = []
275
+ err = GPGME::gpgme_get_key(self, fingerprint, rkey, secret ? 1 : 0)
276
+ exc = GPGME::error_to_exception(err)
277
+ raise exc if exc
278
+ rkey[0]
279
+ end
280
+
281
+ ##
282
+ # Import/export and generation/deletion of keys
283
+ ##
284
+
285
+ # Generate a new key pair.
286
+ # +parms+ is a string which looks like
287
+ #
288
+ # <GnupgKeyParms format="internal">
289
+ # Key-Type: DSA
290
+ # Key-Length: 1024
291
+ # Subkey-Type: ELG-E
292
+ # Subkey-Length: 1024
293
+ # Name-Real: Joe Tester
294
+ # Name-Comment: with stupid passphrase
295
+ # Name-Email: joe@foo.bar
296
+ # Expire-Date: 0
297
+ # Passphrase: abc
298
+ # </GnupgKeyParms>
299
+ #
300
+ # If +pubkey+ and +seckey+ are both set to +nil+, it stores the generated
301
+ # key pair into your key ring.
302
+ def generate_key(parms, pubkey = nil, seckey = nil)
303
+ err = GPGME::gpgme_op_genkey(self, parms, pubkey, seckey)
304
+ exc = GPGME::error_to_exception(err)
305
+ raise exc if exc
306
+ end
307
+ alias genkey generate_key
308
+
309
+ # Extract the public keys that match the +recipients+. Returns a
310
+ # {GPGME::Data} object which is not rewinded (should do +seek(0)+
311
+ # before reading).
312
+ #
313
+ # Private keys cannot be exported due to GPGME restrictions.
314
+ #
315
+ # If passed, the key will be exported to +keydata+, which must be
316
+ # a {GPGME::Data} object.
317
+ def export_keys(recipients, keydata = Data.new)
318
+ err = GPGME::gpgme_op_export(self, recipients, 0, keydata)
319
+ exc = GPGME::error_to_exception(err)
320
+ raise exc if exc
321
+ keydata
322
+ end
323
+ alias export export_keys
324
+
325
+ # Add the keys in the data buffer to the key ring.
326
+ def import_keys(keydata)
327
+ err = GPGME::gpgme_op_import(self, keydata)
328
+ exc = GPGME::error_to_exception(err)
329
+ raise exc if exc
330
+ end
331
+ alias import import_keys
332
+
333
+ def import_result
334
+ GPGME::gpgme_op_import_result(self)
335
+ end
336
+
337
+ # Delete the key from the key ring.
338
+ # If allow_secret is false, only public keys are deleted,
339
+ # otherwise secret keys are deleted as well.
340
+ def delete_key(key, allow_secret = false)
341
+ err = GPGME::gpgme_op_delete(self, key, allow_secret ? 1 : 0)
342
+ exc = GPGME::error_to_exception(err)
343
+ raise exc if exc
344
+ end
345
+ alias delete delete_key
346
+
347
+ # Edit attributes of the key in the local key ring.
348
+ def edit_key(key, editfunc, hook_value = nil, out = Data.new)
349
+ err = GPGME::gpgme_op_edit(self, key, editfunc, hook_value, out)
350
+ exc = GPGME::error_to_exception(err)
351
+ raise exc if exc
352
+ end
353
+ alias edit edit_key
354
+
355
+ # Edit attributes of the key on the card.
356
+ def edit_card_key(key, editfunc, hook_value = nil, out = Data.new)
357
+ err = GPGME::gpgme_op_card_edit(self, key, editfunc, hook_value, out)
358
+ exc = GPGME::error_to_exception(err)
359
+ raise exc if exc
360
+ end
361
+ alias edit_card edit_card_key
362
+ alias card_edit edit_card_key
363
+
364
+ ##
365
+ # Crypto operations
366
+ ##
367
+
368
+ # Decrypt the ciphertext and return the plaintext.
369
+ def decrypt(cipher, plain = Data.new)
370
+ err = GPGME::gpgme_op_decrypt(self, cipher, plain)
371
+ exc = GPGME::error_to_exception(err)
372
+ raise exc if exc
373
+ plain
374
+ end
375
+
376
+ def decrypt_verify(cipher, plain = Data.new)
377
+ err = GPGME::gpgme_op_decrypt_verify(self, cipher, plain)
378
+ exc = GPGME::error_to_exception(err)
379
+ raise exc if exc
380
+ plain
381
+ end
382
+
383
+ def decrypt_result
384
+ GPGME::gpgme_op_decrypt_result(self)
385
+ end
386
+
387
+ # Verify that the signature in the data object is a valid signature.
388
+ def verify(sig, signed_text = nil, plain = Data.new)
389
+ err = GPGME::gpgme_op_verify(self, sig, signed_text, plain)
390
+ exc = GPGME::error_to_exception(err)
391
+ raise exc if exc
392
+ plain
393
+ end
394
+
395
+ def verify_result
396
+ GPGME::gpgme_op_verify_result(self)
397
+ end
398
+
399
+ # Remove the list of signers from this object.
400
+ def clear_signers
401
+ GPGME::gpgme_signers_clear(self)
402
+ end
403
+
404
+ # Add _keys_ to the list of signers.
405
+ def add_signer(*keys)
406
+ keys.each do |key|
407
+ err = GPGME::gpgme_signers_add(self, key)
408
+ exc = GPGME::error_to_exception(err)
409
+ raise exc if exc
410
+ end
411
+ end
412
+
413
+ # Create a signature for the text.
414
+ # +plain+ is a data object which contains the text.
415
+ # +sig+ is a data object where the generated signature is stored.
416
+ def sign(plain, sig = Data.new, mode = GPGME::SIG_MODE_NORMAL)
417
+ err = GPGME::gpgme_op_sign(self, plain, sig, mode)
418
+ exc = GPGME::error_to_exception(err)
419
+ raise exc if exc
420
+ sig
421
+ end
422
+
423
+ def sign_result
424
+ GPGME::gpgme_op_sign_result(self)
425
+ end
426
+
427
+ # Encrypt the plaintext in the data object for the recipients and
428
+ # return the ciphertext.
429
+ def encrypt(recp, plain, cipher = Data.new, flags = 0)
430
+ err = GPGME::gpgme_op_encrypt(self, recp, flags, plain, cipher)
431
+ exc = GPGME::error_to_exception(err)
432
+ raise exc if exc
433
+ cipher
434
+ end
435
+
436
+ def encrypt_result
437
+ GPGME::gpgme_op_encrypt_result(self)
438
+ end
439
+
440
+ def encrypt_sign(recp, plain, cipher = Data.new, flags = 0)
441
+ err = GPGME::gpgme_op_encrypt_sign(self, recp, flags, plain, cipher)
442
+ exc = GPGME::error_to_exception(err)
443
+ raise exc if exc
444
+ cipher
445
+ end
446
+
447
+ def inspect
448
+ "#<#{self.class} protocol=#{PROTOCOL_NAMES[protocol] || protocol}, \
449
+ armor=#{armor}, textmode=#{textmode}, \
450
+ keylist_mode=#{KEYLIST_MODE_NAMES[keylist_mode]}>"
451
+ end
452
+
453
+ private
454
+
455
+ def self.pass_function(pass, uid_hint, passphrase_info, prev_was_bad, fd)
456
+ io = IO.for_fd(fd, 'w')
457
+ io.puts pass
458
+ io.flush
459
+ end
460
+
461
+ end
462
+ end