gpgme-loongson 2.0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,525 @@
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
+ # * +:pinentry_mode+ One of: +PINENTRY_MODE_DEFAULT+,
24
+ # +PINENTRY_MODE_ASK+, +PINENTRY_MODE_CANCEL+,
25
+ # +PINENTRY_MODE_ERROR+, or +PINENTRY_MODE_LOOPBACK+.
26
+ # * +:offline+ if set to true, dirmngr will not contact external services
27
+ # * +:password+ password of the passphrased password being used.
28
+ # * +:passphrase_callback+ A callback function. See {#set_passphrase_callback}.
29
+ # * +:passphrase_callback_value+ An object passed to passphrase_callback.
30
+ # * +:progress_callback+ A callback function. See {#set_progress_callback}.
31
+ # * +:progress_callback_value+ An object passed to progress_callback.
32
+ # * +:status_callback+ A callback function. See {#set_status_callback}.
33
+ # * +:status_callback_value+ An object passed to status_callback.
34
+ #
35
+ # @example
36
+ # ctx = GPGME::Ctx.new
37
+ # # operate on ctx
38
+ # ctx.release
39
+ #
40
+ # @example
41
+ # GPGME::Ctx.new do |ctx|
42
+ # # operate on ctx
43
+ # end
44
+ #
45
+ def self.new(options = {})
46
+ rctx = []
47
+ err = GPGME::gpgme_new(rctx)
48
+ exc = GPGME::error_to_exception(err)
49
+ raise exc if exc
50
+ ctx = rctx[0]
51
+
52
+ ctx.protocol = options[:protocol] if options[:protocol]
53
+ ctx.armor = options[:armor] if options[:armor]
54
+ ctx.textmode = options[:textmode] if options[:textmode]
55
+ ctx.keylist_mode = options[:keylist_mode] if options[:keylist_mode]
56
+ ctx.pinentry_mode = options[:pinentry_mode] if options[:pinentry_mode]
57
+ ctx.offline = options[:offline] if options[:offline]
58
+
59
+ if options[:password]
60
+ ctx.set_passphrase_callback GPGME::Ctx.method(:pass_function),
61
+ options[:password]
62
+ else
63
+ if options[:passphrase_callback]
64
+ ctx.set_passphrase_callback options[:passphrase_callback],
65
+ options[:passphrase_callback_value]
66
+ end
67
+ end
68
+ if options[:progress_callback]
69
+ ctx.set_progress_callback options[:progress_callback],
70
+ options[:progress_callback_value]
71
+ end
72
+ if options[:status_callback]
73
+ ctx.set_status_callback options[:status_callback],
74
+ options[:status_callback_value]
75
+ end
76
+
77
+ if block_given?
78
+ begin
79
+ yield ctx
80
+ ensure
81
+ GPGME::gpgme_release(ctx)
82
+ end
83
+ else
84
+ ctx
85
+ end
86
+ end
87
+
88
+
89
+ ##
90
+ # Releases the Ctx instance. Must be called if it was initialized without
91
+ # a block.
92
+ #
93
+ # @example
94
+ # ctx = GPGME::Ctx.new
95
+ # # operate on ctx
96
+ # ctx.release
97
+ #
98
+ def release
99
+ GPGME::gpgme_release(self)
100
+ end
101
+
102
+ ##
103
+ # Getters and setters
104
+ ##
105
+
106
+ # Set the +protocol+ used within this context. See {GPGME::Ctx.new} for
107
+ # possible values.
108
+ def protocol=(proto)
109
+ err = GPGME::gpgme_set_protocol(self, proto)
110
+ exc = GPGME::error_to_exception(err)
111
+ raise exc if exc
112
+ proto
113
+ end
114
+
115
+ # Return the +protocol+ used within this context.
116
+ def protocol
117
+ GPGME::gpgme_get_protocol(self)
118
+ end
119
+
120
+ # Tell whether the output should be ASCII armored.
121
+ def armor=(yes)
122
+ GPGME::gpgme_set_armor(self, yes ? 1 : 0)
123
+ yes
124
+ end
125
+
126
+ # Return true if the output is ASCII armored.
127
+ def armor
128
+ GPGME::gpgme_get_armor(self) == 1 ? true : false
129
+ end
130
+
131
+ # Tell whether canonical text mode should be used.
132
+ def textmode=(yes)
133
+ GPGME::gpgme_set_textmode(self, yes ? 1 : 0)
134
+ yes
135
+ end
136
+
137
+ # Return true if canonical text mode is enabled.
138
+ def textmode
139
+ GPGME::gpgme_get_textmode(self) == 1 ? true : false
140
+ end
141
+
142
+ # Change the default behaviour of the key listing functions.
143
+ def keylist_mode=(mode)
144
+ GPGME::gpgme_set_keylist_mode(self, mode)
145
+ mode
146
+ end
147
+
148
+ # Return the current key listing mode.
149
+ def keylist_mode
150
+ GPGME::gpgme_get_keylist_mode(self)
151
+ end
152
+
153
+ # Change the default behaviour of the pinentry invocation.
154
+ def pinentry_mode=(mode)
155
+ GPGME::gpgme_set_pinentry_mode(self, mode)
156
+ mode
157
+ end
158
+
159
+ # Return the current pinentry mode.
160
+ def pinentry_mode
161
+ GPGME::gpgme_get_pinentry_mode(self)
162
+ end
163
+
164
+ # Change the default behaviour of the dirmngr that might require
165
+ # connections to external services.
166
+ def offline=(mode)
167
+ GPGME::gpgme_set_offline(self, mode)
168
+ mode
169
+ end
170
+
171
+ # Return the current offline mode.
172
+ def offline
173
+ GPGME::gpgme_get_offline(self)
174
+ end
175
+
176
+ ##
177
+ # Passphrase and progress callbacks
178
+ ##
179
+
180
+ # Set the passphrase callback with given hook value.
181
+ # +passfunc+ should respond to +call+ with 5 arguments.
182
+ #
183
+ # * +obj+ the parameter +:passphrase_callback_value+ passed when creating
184
+ # the {GPGME::Ctx} object.
185
+ # * +uid_hint+ hint as to what key are we asking the password for. Ex:
186
+ #
187
+ # +CFB3294A50C2CFD7 Albert Llop <mrsimo@example.com>+
188
+ #
189
+ # * +passphrase_info+
190
+ # * +prev_was_bad+ 0 if it's the first time the password is being asked,
191
+ # 1 otherwise.
192
+ # * +fd+ file descriptor where the password must be written too.
193
+ #
194
+ # Expects a Method object which can be obtained by the +method+ method
195
+ # (really..).
196
+ #
197
+ # ctx.set_passphrase_callback(MyModule.method(:passfunc))
198
+ #
199
+ # @example this method will simply return +maria+ as password.
200
+ # def pass_function(obj, uid_hint, passphrase_info, prev_was_bad, fd)
201
+ # io = IO.for_fd(fd, 'w')
202
+ # io.puts "maria"
203
+ # io.flush
204
+ # end
205
+ #
206
+ # @example this will interactively ask for the password
207
+ # def passfunc(obj, uid_hint, passphrase_info, prev_was_bad, fd)
208
+ # $stderr.write("Passphrase for #{uid_hint}: ")
209
+ # $stderr.flush
210
+ # begin
211
+ # system('stty -echo')
212
+ # io = IO.for_fd(fd, 'w')
213
+ # io.puts(gets)
214
+ # io.flush
215
+ # ensure
216
+ # (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
217
+ # system('stty echo')
218
+ # end
219
+ # $stderr.puts
220
+ # end
221
+ #
222
+ # Note that this function doesn't work with GnuPG 2.0. You can
223
+ # use either GnuPG 1.x, which can be installed in parallel with
224
+ # GnuPG 2.0, or GnuPG 2.1, which has loopback pinentry feature (see
225
+ # {#pinentry_mode}).
226
+ def set_passphrase_callback(passfunc, hook_value = nil)
227
+ GPGME::gpgme_set_passphrase_cb(self, passfunc, hook_value)
228
+ end
229
+ alias set_passphrase_cb set_passphrase_callback
230
+
231
+ # Set the progress callback with given hook value.
232
+ # <i>progfunc</i> should respond to <code>call</code> with 5 arguments.
233
+ #
234
+ # def progfunc(hook, what, type, current, total)
235
+ # $stderr.write("#{what}: #{current}/#{total}\r")
236
+ # $stderr.flush
237
+ # end
238
+ #
239
+ # ctx.set_progress_callback(method(:progfunc))
240
+ #
241
+ def set_progress_callback(progfunc, hook_value = nil)
242
+ GPGME::gpgme_set_progress_cb(self, progfunc, hook_value)
243
+ end
244
+ alias set_progress_cb set_progress_callback
245
+
246
+ # Set the status callback with given hook value.
247
+ # +statusfunc+ should respond to +call+ with 3 arguments.
248
+ #
249
+ # * +obj+ the parameter +:status_callback_value+ passed when creating
250
+ # the {GPGME::Ctx} object.
251
+ # * +keyword+ the name of the status message
252
+ # * +args+ any arguments for the status message
253
+ #
254
+ # def status_function(obj, keyword, args)
255
+ # $stderr.puts("#{keyword} #{args}")
256
+ # return 0
257
+ # end
258
+ def set_status_callback(statusfunc, hook_value = nil)
259
+ GPGME::gpgme_set_status_cb(self, statusfunc, hook_value)
260
+ end
261
+ alias set_status_cb set_status_callback
262
+
263
+ ##
264
+ # Searching and iterating through keys. Used by {GPGME::Key.find}
265
+ ##
266
+
267
+ # Initiate a key listing operation for given pattern. If +pattern+ is
268
+ # +nil+, all available keys are returned. If +secret_only<+ is +true+,
269
+ # only secret keys are returned.
270
+ #
271
+ # Used by {GPGME::Ctx#each_key}
272
+ def keylist_start(pattern = nil, secret_only = false)
273
+ err = GPGME::gpgme_op_keylist_start(self, pattern, secret_only ? 1 : 0)
274
+ exc = GPGME::error_to_exception(err)
275
+ raise exc if exc
276
+ end
277
+
278
+ # Advance to the next key in the key listing operation.
279
+ #
280
+ # Used by {GPGME::Ctx#each_key}
281
+ def keylist_next
282
+ rkey = []
283
+ err = GPGME::gpgme_op_keylist_next(self, rkey)
284
+ exc = GPGME::error_to_exception(err)
285
+ raise exc if exc
286
+ rkey[0]
287
+ end
288
+
289
+ # End a pending key list operation.
290
+ #
291
+ # Used by {GPGME::Ctx#each_key}
292
+ def keylist_end
293
+ err = GPGME::gpgme_op_keylist_end(self)
294
+ exc = GPGME::error_to_exception(err)
295
+ raise exc if exc
296
+ end
297
+
298
+ # Convenient method to iterate over keys.
299
+ #
300
+ # If +pattern+ is +nil+, all available keys are returned. If +secret_only+
301
+ # is +true+, only secret keys are returned.
302
+ #
303
+ # See {GPGME::Key.find} for an example of how to use, or for an easier way
304
+ # to use.
305
+ def each_key(pattern = nil, secret_only = false, &block)
306
+ keylist_start(pattern, secret_only)
307
+ begin
308
+ loop { yield keylist_next }
309
+ rescue EOFError
310
+ # The last key in the list has already been returned.
311
+ ensure
312
+ keylist_end
313
+ end
314
+ end
315
+ alias each_keys each_key
316
+
317
+ # Returns the keys that match the +pattern+, or all if +pattern+ is nil.
318
+ # Returns only secret keys if +secret_only+ is true.
319
+ def keys(pattern = nil, secret_only = nil)
320
+ keys = []
321
+ each_key(pattern, secret_only) do |key|
322
+ keys << key
323
+ end
324
+ keys
325
+ end
326
+
327
+ # Get the key with the +fingerprint+.
328
+ # If +secret+ is +true+, secret key is returned.
329
+ def get_key(fingerprint, secret = false)
330
+ rkey = []
331
+ err = GPGME::gpgme_get_key(self, fingerprint, rkey, secret ? 1 : 0)
332
+ exc = GPGME::error_to_exception(err)
333
+ raise exc if exc
334
+ rkey[0]
335
+ end
336
+
337
+ ##
338
+ # Import/export and generation/deletion of keys
339
+ ##
340
+
341
+ # Generate a new key pair.
342
+ # +parms+ is a string which looks like
343
+ #
344
+ # <GnupgKeyParms format="internal">
345
+ # Key-Type: DSA
346
+ # Key-Length: 1024
347
+ # Subkey-Type: ELG-E
348
+ # Subkey-Length: 1024
349
+ # Name-Real: Joe Tester
350
+ # Name-Comment: with stupid passphrase
351
+ # Name-Email: joe@foo.bar
352
+ # Expire-Date: 0
353
+ # Passphrase: abc
354
+ # </GnupgKeyParms>
355
+ #
356
+ # If +pubkey+ and +seckey+ are both set to +nil+, it stores the generated
357
+ # key pair into your key ring.
358
+ def generate_key(parms, pubkey = nil, seckey = nil)
359
+ err = GPGME::gpgme_op_genkey(self, parms, pubkey, seckey)
360
+ exc = GPGME::error_to_exception(err)
361
+ raise exc if exc
362
+ end
363
+ alias genkey generate_key
364
+
365
+ # Extract the public keys that match the +recipients+. Returns a
366
+ # {GPGME::Data} object which is not rewinded (should do +seek(0)+
367
+ # before reading).
368
+ #
369
+ # Private keys cannot be exported due to GPGME restrictions.
370
+ #
371
+ # If passed, the key will be exported to +keydata+, which must be
372
+ # a {GPGME::Data} object.
373
+ def export_keys(recipients, keydata = Data.new)
374
+ err = GPGME::gpgme_op_export(self, recipients, 0, keydata)
375
+ exc = GPGME::error_to_exception(err)
376
+ raise exc if exc
377
+ keydata
378
+ end
379
+ alias export export_keys
380
+
381
+ # Add the keys in the data buffer to the key ring.
382
+ def import_keys(keydata)
383
+ err = GPGME::gpgme_op_import(self, keydata)
384
+ exc = GPGME::error_to_exception(err)
385
+ raise exc if exc
386
+ end
387
+ alias import import_keys
388
+
389
+ def import_result
390
+ GPGME::gpgme_op_import_result(self)
391
+ end
392
+
393
+ # Delete the key from the key ring.
394
+ # If allow_secret is false, only public keys are deleted,
395
+ # otherwise secret keys are deleted as well.
396
+ def delete_key(key, allow_secret = false)
397
+ err = GPGME::gpgme_op_delete(self, key, allow_secret ? 1 : 0)
398
+ exc = GPGME::error_to_exception(err)
399
+ raise exc if exc
400
+ end
401
+ alias delete delete_key
402
+
403
+ # Edit attributes of the key in the local key ring.
404
+ def edit_key(key, editfunc, hook_value = nil, out = Data.new)
405
+ err = GPGME::gpgme_op_edit(self, key, editfunc, hook_value, out)
406
+ exc = GPGME::error_to_exception(err)
407
+ raise exc if exc
408
+ end
409
+ alias edit edit_key
410
+
411
+ # Edit attributes of the key on the card.
412
+ def edit_card_key(key, editfunc, hook_value = nil, out = Data.new)
413
+ err = GPGME::gpgme_op_card_edit(self, key, editfunc, hook_value, out)
414
+ exc = GPGME::error_to_exception(err)
415
+ raise exc if exc
416
+ end
417
+ alias edit_card edit_card_key
418
+ alias card_edit edit_card_key
419
+
420
+ ##
421
+ # Crypto operations
422
+ ##
423
+
424
+ # Decrypt the ciphertext and return the plaintext.
425
+ def decrypt(cipher, plain = Data.new)
426
+ err = GPGME::gpgme_op_decrypt(self, cipher, plain)
427
+ exc = GPGME::error_to_exception(err)
428
+ raise exc if exc
429
+ plain
430
+ end
431
+
432
+ def decrypt_verify(cipher, plain = Data.new)
433
+ err = GPGME::gpgme_op_decrypt_verify(self, cipher, plain)
434
+ exc = GPGME::error_to_exception(err)
435
+ raise exc if exc
436
+ plain
437
+ end
438
+
439
+ def decrypt_result
440
+ GPGME::gpgme_op_decrypt_result(self)
441
+ end
442
+
443
+ # Verify that the signature in the data object is a valid signature.
444
+ def verify(sig, signed_text = nil, plain = Data.new)
445
+ err = GPGME::gpgme_op_verify(self, sig, signed_text, plain)
446
+ exc = GPGME::error_to_exception(err)
447
+ raise exc if exc
448
+ plain
449
+ end
450
+
451
+ def verify_result
452
+ GPGME::gpgme_op_verify_result(self)
453
+ end
454
+
455
+ # Remove the list of signers from this object.
456
+ def clear_signers
457
+ GPGME::gpgme_signers_clear(self)
458
+ end
459
+
460
+ # Add _keys_ to the list of signers.
461
+ def add_signer(*keys)
462
+ keys.each do |key|
463
+ err = GPGME::gpgme_signers_add(self, key)
464
+ exc = GPGME::error_to_exception(err)
465
+ raise exc if exc
466
+ end
467
+ end
468
+
469
+ # Create a signature for the text.
470
+ # +plain+ is a data object which contains the text.
471
+ # +sig+ is a data object where the generated signature is stored.
472
+ def sign(plain, sig = Data.new, mode = GPGME::SIG_MODE_NORMAL)
473
+ err = GPGME::gpgme_op_sign(self, plain, sig, mode)
474
+ exc = GPGME::error_to_exception(err)
475
+ raise exc if exc
476
+ sig
477
+ end
478
+
479
+ def sign_result
480
+ GPGME::gpgme_op_sign_result(self)
481
+ end
482
+
483
+ # Encrypt the plaintext in the data object for the recipients and
484
+ # return the ciphertext.
485
+ def encrypt(recp, plain, cipher = Data.new, flags = 0)
486
+ err = GPGME::gpgme_op_encrypt(self, recp, flags, plain, cipher)
487
+ exc = GPGME::error_to_exception(err)
488
+ raise exc if exc
489
+ cipher
490
+ end
491
+
492
+ def encrypt_result
493
+ GPGME::gpgme_op_encrypt_result(self)
494
+ end
495
+
496
+ def encrypt_sign(recp, plain, cipher = Data.new, flags = 0)
497
+ err = GPGME::gpgme_op_encrypt_sign(self, recp, flags, plain, cipher)
498
+ exc = GPGME::error_to_exception(err)
499
+ raise exc if exc
500
+ cipher
501
+ end
502
+
503
+ def spawn(file, argv, datain, dataout, dataerr, flags = 0)
504
+ err = GPGME::gpgme_op_spawn(self, file, argv, datain, dataout, dataerr,
505
+ flags)
506
+ exc = GPGME::error_to_exception(err)
507
+ raise exc if exc
508
+ end
509
+
510
+ def inspect
511
+ "#<#{self.class} protocol=#{PROTOCOL_NAMES[protocol] || protocol}, \
512
+ armor=#{armor}, textmode=#{textmode}, \
513
+ keylist_mode=#{KEYLIST_MODE_NAMES[keylist_mode]}>"
514
+ end
515
+
516
+ private
517
+
518
+ def self.pass_function(pass, uid_hint, passphrase_info, prev_was_bad, fd)
519
+ io = IO.for_fd(fd, 'w')
520
+ io.puts pass
521
+ io.flush
522
+ end
523
+
524
+ end
525
+ end