gpgme 1.0.8 → 2.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.
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
@@ -29,7 +29,7 @@ unless ENV['GNUPGHOME']
29
29
  $stderr.flush
30
30
  exit(1) unless gets.chomp == 'y'
31
31
  end
32
-
32
+
33
33
  def progfunc(hook, what, type, current, total)
34
34
  $stderr.write("#{what}: #{current}/#{total}\r")
35
35
  $stderr.flush
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'gpgme'
3
3
 
4
- GPGME.list_keys(ARGV.shift) do |key|
4
+ ctx = GPGME::Ctx.new
5
+ ctx.each_key(ARGV.shift) do |key|
5
6
  puts(key)
6
7
  end
@@ -28,12 +28,15 @@ plain = 'test test test'
28
28
  puts("Plaintext:\n#{plain}")
29
29
 
30
30
  # Perform symmetric encryption on PLAIN.
31
- cipher = GPGME::encrypt(nil, plain, {:armor => true,
31
+ crypto = GPGME::Crypto.new(:armor => true)
32
+ cipher = crypto.encrypt(plain, {:symmetric => true,
32
33
  # :passphrase_callback => method(:passfunc)
33
34
  })
34
- puts("Ciphertext:\n#{cipher}")
35
+ str = cipher.read
36
+ puts("Ciphertext:\n#{str}")
35
37
 
36
- plain = GPGME::decrypt(cipher, {
38
+ cipher = GPGME::Data.new(str)
39
+ plain = crypto.decrypt(cipher, {
37
40
  # :passphrase_callback => method(:passfunc)
38
41
  })
39
- puts("Plaintext:\n#{plain}")
42
+ puts("Plaintext:\n#{plain.read}")
@@ -24,6 +24,8 @@ unless ENV['GPG_AGENT_INFO']
24
24
  exit(1)
25
25
  end
26
26
 
27
- puts GPGME::clearsign('test test test', {
28
- # :passphrase_callback => method(:passfunc)
29
- })
27
+ crypto = GPGME::Crypto.new
28
+ signature = crypto.clearsign('test test test', {
29
+ # :passphrase_callback => method(:passfunc)
30
+ })
31
+ puts signature.read
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'gpgme'
3
3
 
4
- GPGME::verify(ARGF.read, nil, $stdout) do |signature|
5
- puts(signature.to_s)
4
+ crypto = GPGME::Crypto.new
5
+ signature = GPGME::Data.new(ARGF.read)
6
+ crypto.verify(signature) do |sig|
7
+ puts(sig.to_s)
6
8
  end
@@ -0,0 +1,58 @@
1
+ require 'mkmf'
2
+
3
+ BUILD = Dir::pwd
4
+ SRC = File.expand_path(File.dirname(__FILE__))
5
+ PREFIX = "#{BUILD}/dst/"
6
+
7
+ def sys(*cmd)
8
+ puts " -- #{cmd.join(' ')}"
9
+
10
+ unless ret = xsystem(cmd.join(' '))
11
+ raise "#{cmd.join(' ')} failed!"
12
+ end
13
+
14
+ ret
15
+ end
16
+
17
+ def build(tgz, *flags)
18
+ sys("tar xjvf #{tgz}")
19
+
20
+ Dir.chdir(File.basename(tgz, '.tar.bz2')) do
21
+ sys("./configure --prefix=#{PREFIX} --disable-shared --enable-static --with-pic", *flags)
22
+ sys("make")
23
+ sys("make install")
24
+ end
25
+ end
26
+
27
+ libgpg_error_tgz = File.join(SRC, 'libgpg-error-1.10.tar.bz2')
28
+ libassuan_tgz = File.join(SRC, 'libassuan-2.0.2.tar.bz2')
29
+ gpgme_tgz = File.join(SRC, 'gpgme-1.3.1.tar.bz2')
30
+
31
+ # build deps
32
+
33
+ build(libgpg_error_tgz, "--disable-nls")
34
+ build(libassuan_tgz, "--with-gpg-error-prefix=#{PREFIX}")
35
+ build(gpgme_tgz, "--with-gpg-error-prefix=#{PREFIX}", "--with-libassuan-prefix=#{PREFIX}")
36
+
37
+ # copy gpgme
38
+
39
+
40
+ %w[ libassuan libgpg-error libgpgme ].each do |lib|
41
+ FileUtils.cp "#{PREFIX}/lib/#{lib}.a", "#{BUILD}/#{lib}_ext.a"
42
+ end
43
+
44
+ $INCFLAGS[0,0] = " -I#{PREFIX}/include "
45
+ #$LDFLAGS << " -L#{PREFIX}/lib "
46
+ $CFLAGS << " -fPIC "
47
+
48
+ # build gpgme extension
49
+
50
+ unless have_library 'gpg-error_ext' and have_library 'gpgme_ext' and have_library 'assuan_ext' and have_library 'gpg-error_ext' and have_header 'gpgme.h'
51
+ STDERR.puts "\n\n"
52
+ STDERR.puts "*********************************************************"
53
+ STDERR.puts "********* error compiling and linking libgpgme. *********"
54
+ STDERR.puts "*********************************************************"
55
+ exit(1)
56
+ end
57
+
58
+ create_makefile ('gpgme_n')
@@ -228,7 +228,7 @@ rb_s_gpgme_data_new (VALUE dummy, VALUE rdh)
228
228
  if (gpgme_err_code(err) == GPG_ERR_NO_ERROR)
229
229
  rb_ary_store (rdh, 0, WRAP_GPGME_DATA(dh));
230
230
  return LONG2NUM(err);
231
- }
231
+ }
232
232
 
233
233
  static VALUE
234
234
  rb_s_gpgme_data_new_from_mem (VALUE dummy, VALUE rdh, VALUE vbuffer,
@@ -249,7 +249,7 @@ rb_s_gpgme_data_new_from_mem (VALUE dummy, VALUE rdh, VALUE vbuffer,
249
249
  rb_ary_store (rdh, 0, vdh);
250
250
  }
251
251
  return LONG2NUM(err);
252
- }
252
+ }
253
253
 
254
254
  static VALUE
255
255
  rb_s_gpgme_data_new_from_fd (VALUE dummy, VALUE rdh, VALUE vfd)
@@ -494,7 +494,7 @@ rb_s_gpgme_set_textmode (VALUE dummy, VALUE vctx, VALUE vyes)
494
494
  rb_raise (rb_eArgError, "released ctx");
495
495
  gpgme_set_textmode (ctx, NUM2INT(vyes));
496
496
  return Qnil;
497
- }
497
+ }
498
498
 
499
499
  static VALUE
500
500
  rb_s_gpgme_get_textmode (VALUE dummy, VALUE vctx)
@@ -507,7 +507,7 @@ rb_s_gpgme_get_textmode (VALUE dummy, VALUE vctx)
507
507
  rb_raise (rb_eArgError, "released ctx");
508
508
  yes = gpgme_get_textmode (ctx);
509
509
  return INT2FIX(yes);
510
- }
510
+ }
511
511
 
512
512
  static VALUE
513
513
  rb_s_gpgme_set_include_certs (VALUE dummy, VALUE vctx, VALUE vnr_of_certs)
@@ -609,7 +609,7 @@ rb_s_gpgme_get_passphrase_cb (VALUE dummy, VALUE vctx, VALUE rpassfunc,
609
609
  return Qnil;
610
610
  }
611
611
 
612
- static void
612
+ static void
613
613
  progress_cb (void *hook, const char *what, int type, int current, int total)
614
614
  {
615
615
  VALUE vcb = (VALUE)hook, vprogfunc, vhook_value;
@@ -657,7 +657,7 @@ rb_s_gpgme_set_locale (VALUE dummy, VALUE vctx, VALUE vcategory, VALUE vvalue)
657
657
  {
658
658
  gpgme_ctx_t ctx;
659
659
  gpgme_error_t err;
660
-
660
+
661
661
  UNWRAP_GPGME_CTX(vctx, ctx);
662
662
  if (!ctx)
663
663
  rb_raise (rb_eArgError, "released ctx");
@@ -1518,7 +1518,7 @@ rb_s_gpgme_op_verify_result (VALUE dummy, VALUE vctx)
1518
1518
  gpgme_verify_result_t verify_result;
1519
1519
  gpgme_signature_t signature;
1520
1520
  VALUE vverify_result, vsignatures = rb_ary_new ();
1521
-
1521
+
1522
1522
  UNWRAP_GPGME_CTX(vctx, ctx);
1523
1523
  if (!ctx)
1524
1524
  rb_raise (rb_eArgError, "released ctx");
@@ -1924,7 +1924,7 @@ rb_s_gpgme_wait (VALUE dummy, VALUE vctx, VALUE rstatus, VALUE vhang)
1924
1924
  return Qnil;
1925
1925
  }
1926
1926
 
1927
- void
1927
+ void
1928
1928
  Init_gpgme_n (void)
1929
1929
  {
1930
1930
  VALUE mGPGME;
@@ -1,1561 +1,108 @@
1
- =begin rdoc
2
- = What's this?
3
-
4
- Ruby-GPGME is a Ruby language binding of GPGME (GnuPG Made Easy).
5
-
6
- = Requirements
7
-
8
- - Ruby 1.8 or later
9
- - GPGME 1.1.2 or later http://www.gnupg.org/(en)/related_software/gpgme/index.html
10
- - gpg-agent (optional, but recommended)
11
-
12
- = Installation
13
-
14
- $ gem install ruby-gpgme
15
-
16
- or
17
-
18
- $ ruby extconf.rb
19
- $ make
20
- $ make install
21
-
22
- = Examples
23
-
24
- <tt>examples/genkey.rb</tt>:: Generate a key pair in your keyring.
25
- <tt>examples/keylist.rb</tt>:: List your keyring like gpg --list-keys.
26
- <tt>examples/roundtrip.rb</tt>:: Encrypt and decrypt a plain text.
27
- <tt>examples/sign.rb</tt>:: Create a clear text signature.
28
- <tt>examples/verify.rb</tt>:: Verify a clear text signature given from stdin.
29
-
30
- = API
31
-
32
- Ruby-GPGME provides three levels of API. The highest level API is
33
- close to the command line interface of GnuPG. The mid level API looks
34
- object-oriented (or rubyish). The lowest level API is close to the C
35
- interface of GPGME.
36
-
37
- == The highest level API
38
-
39
- It can be written in the highest level API to create a cleartext
40
- signature of the plaintext from stdin as follows.
41
-
42
- $ ruby -rgpgme -e 'GPGME.clearsign($stdin, $stdout)'
43
-
44
- == The mid level API
45
-
46
- The same example can be rewritten in the mid level API as follows.
47
-
48
- $ ruby -rgpgme -e <<End
49
- ctx = GPGME::Ctx.new
50
- plain = GPGME::Data.from_io($stdin)
51
- sig = GPGME::Data.from_io($stdout)
52
- ctx.sign(plain, sig, GPGME::SIG_MODE_CLEAR)
53
- End
54
-
55
- == The lowest level API
56
-
57
- The same example can be rewritten in the lowest level API as follows.
58
-
59
- $ ruby -rgpgme -e <<End
60
- ret = Array.new
61
- GPGME::gpgme_new(ret)
62
- ctx = ret.shift
63
- GPGME::gpgme_data_new_from_fd(ret, 0)
64
- plain = ret.shift
65
- GPGME::gpgme_data_new_from_fd(ret, 1)
66
- sig = ret.shift
67
- GPGME::gpgme_op_sign(ctx, plain, sig, GPGME::SIG_MODE_CLEAR)
68
- End
69
-
70
- As you see, it's much harder to write a program in this API than the
71
- higher level API. However, if you are already familier with the C
72
- interface of GPGME and/or want to control detailed behavior of GPGME,
73
- it might be useful.
74
-
75
- = License
76
-
77
- Copyright (C) 2003,2006,2007,2008,2009 Daiki Ueno
78
-
79
- This file is a part of Ruby-GPGME.
80
-
81
- Ruby-GPGME is free software; you can redistribute it and/or
82
- modify it under the terms of the GNU Lesser General Public
83
- License as published by the Free Software Foundation; either
84
- version 2.1 of the License, or (at your option) any later version.
85
-
86
- Ruby-GPGME is distributed in the hope that it will be useful,
87
- but WITHOUT ANY WARRANTY; without even the implied warranty of
88
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
89
- Lesser General Public License for more details.
90
-
91
- You should have received a copy of the GNU Lesser General Public
92
- License along with this library; if not, write to the Free Software
93
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
94
- =end
95
- module GPGME
96
- VERSION = "1.0.8"
97
- end
1
+ $:.push File.expand_path("../..", __FILE__) # C extension is in the root
98
2
 
99
3
  require 'gpgme_n'
100
- require 'gpgme/constants'
101
-
102
- # call-seq:
103
- # GPGME.decrypt(cipher, plain=nil, options=Hash.new){|signature| ...}
104
- #
105
- # <code>GPGME.decrypt</code> performs decryption.
106
- #
107
- # The arguments should be specified as follows.
108
- #
109
- # - GPGME.decrypt(<i>cipher</i>, <i>plain</i>, <i>options</i>)
110
- # - GPGME.decrypt(<i>cipher</i>, <i>options</i>) -> <i>plain</i>
111
- #
112
- # All arguments except <i>cipher</i> are optional. <i>cipher</i> is
113
- # input, and <i>plain</i> is output. If the last argument is a
114
- # Hash, options will be read from it.
115
- #
116
- # An input argument is specified by an IO like object (which responds
117
- # to <code>read</code>), a string, or a GPGME::Data object.
118
- #
119
- # An output argument is specified by an IO like object (which responds
120
- # to <code>write</code>) or a GPGME::Data object.
121
- #
122
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code>.
123
- #
124
- def GPGME.decrypt(cipher, *args_options)
125
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 2
126
- args, options = split_args(args_options)
127
- plain = args[0]
128
-
129
- check_version(options)
130
- GPGME::Ctx.new(options) do |ctx|
131
- cipher_data = input_data(cipher)
132
- plain_data = output_data(plain)
133
- begin
134
- ctx.decrypt_verify(cipher_data, plain_data)
135
- rescue GPGME::Error::UnsupportedAlgorithm => exc
136
- exc.algorithm = ctx.decrypt_result.unsupported_algorithm
137
- raise exc
138
- rescue GPGME::Error::WrongKeyUsage => exc
139
- exc.key_usage = ctx.decrypt_result.wrong_key_usage
140
- raise exc
141
- end
142
-
143
- verify_result = ctx.verify_result
144
- if verify_result && block_given?
145
- verify_result.signatures.each do |signature|
146
- yield signature
147
- end
148
- end
149
-
150
- unless plain
151
- plain_data.seek(0, IO::SEEK_SET)
152
- plain_data.read
153
- end
154
- end
155
- end
156
-
157
- # call-seq:
158
- # GPGME.verify(sig, signed_text=nil, plain=nil, options=Hash.new){|signature| ...}
159
- #
160
- # <code>GPGME.verify</code> verifies a signature.
161
- #
162
- # The arguments should be specified as follows.
163
- #
164
- # - GPGME.verify(<i>sig</i>, <i>signed_text</i>, <i>plain</i>, <i>options</i>)
165
- # - GPGME.verify(<i>sig</i>, <i>signed_text</i>, <i>options</i>) -> <i>plain</i>
166
- #
167
- # All arguments except <i>sig</i> are optional. <i>sig</i> and
168
- # <i>signed_text</i> are input. <i>plain</i> is output. If the last
169
- # argument is a Hash, options will be read from it.
170
- #
171
- # An input argument is specified by an IO like object (which responds
172
- # to <code>read</code>), a string, or a GPGME::Data object.
173
- #
174
- # An output argument is specified by an IO like object (which responds
175
- # to <code>write</code>) or a GPGME::Data object.
176
- #
177
- # If <i>sig</i> is a detached signature, then the signed text should
178
- # be provided in <i>signed_text</i> and <i>plain</i> should be
179
- # <tt>nil</tt>. Otherwise, if <i>sig</i> is a normal (or cleartext)
180
- # signature, <i>signed_text</i> should be <tt>nil</tt>.
181
- #
182
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code>.
183
- #
184
- def GPGME.verify(sig, *args_options) # :yields: signature
185
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 3
186
- args, options = split_args(args_options)
187
- signed_text, plain = args
188
-
189
- check_version(options)
190
- GPGME::Ctx.new(options) do |ctx|
191
- sig_data = input_data(sig)
192
- if signed_text
193
- signed_text_data = input_data(signed_text)
194
- plain_data = nil
195
- else
196
- signed_text_data = nil
197
- plain_data = output_data(plain)
198
- end
199
- ctx.verify(sig_data, signed_text_data, plain_data)
200
- ctx.verify_result.signatures.each do |signature|
201
- yield signature
202
- end
203
- if !signed_text && !plain
204
- plain_data.seek(0, IO::SEEK_SET)
205
- plain_data.read
206
- end
207
- end
208
- end
209
-
210
- # call-seq:
211
- # GPGME.sign(plain, sig=nil, options=Hash.new)
212
- #
213
- # <code>GPGME.sign</code> creates a signature of the plaintext.
214
- #
215
- # The arguments should be specified as follows.
216
- #
217
- # - GPGME.sign(<i>plain</i>, <i>sig</i>, <i>options</i>)
218
- # - GPGME.sign(<i>plain</i>, <i>options</i>) -> <i>sig</i>
219
- #
220
- # All arguments except <i>plain</i> are optional. <i>plain</i> is
221
- # input and <i>sig</i> is output. If the last argument is a Hash,
222
- # options will be read from it.
223
- #
224
- # An input argument is specified by an IO like object (which responds
225
- # to <code>read</code>), a string, or a GPGME::Data object.
226
- #
227
- # An output argument is specified by an IO like object (which responds
228
- # to <code>write</code>) or a GPGME::Data object.
229
- #
230
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code> except for
231
- #
232
- # - <tt>:signers</tt> Signing keys. If specified, it is an array
233
- # whose elements are a GPGME::Key object or a string.
234
- # - <tt>:mode</tt> Desired type of a signature. Either
235
- # <tt>GPGME::SIG_MODE_NORMAL</tt> for a normal signature,
236
- # <tt>GPGME::SIG_MODE_DETACH</tt> for a detached signature, or
237
- # <tt>GPGME::SIG_MODE_CLEAR</tt> for a cleartext signature.
238
- #
239
- def GPGME.sign(plain, *args_options)
240
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 2
241
- args, options = split_args(args_options)
242
- sig = args[0]
243
-
244
- check_version(options)
245
- GPGME::Ctx.new(options) do |ctx|
246
- ctx.add_signer(*resolve_keys(options[:signers], true, [:sign])) if options[:signers]
247
- mode = options[:mode] || GPGME::SIG_MODE_NORMAL
248
- plain_data = input_data(plain)
249
- sig_data = output_data(sig)
250
- begin
251
- ctx.sign(plain_data, sig_data, mode)
252
- rescue GPGME::Error::UnusableSecretKey => exc
253
- exc.keys = ctx.sign_result.invalid_signers
254
- raise exc
255
- end
256
-
257
- unless sig
258
- sig_data.seek(0, IO::SEEK_SET)
259
- sig_data.read
260
- end
261
- end
262
- end
263
-
264
- # call-seq:
265
- # GPGME.clearsign(plain, sig=nil, options=Hash.new)
266
- #
267
- # <code>GPGME.clearsign</code> creates a cleartext signature of the plaintext.
268
- #
269
- # The arguments should be specified as follows.
270
- #
271
- # - GPGME.clearsign(<i>plain</i>, <i>sig</i>, <i>options</i>)
272
- # - GPGME.clearsign(<i>plain</i>, <i>options</i>) -> <i>sig</i>
273
- #
274
- # All arguments except <i>plain</i> are optional. <i>plain</i> is
275
- # input and <i>sig</i> is output. If the last argument is a Hash,
276
- # options will be read from it.
277
- #
278
- # An input argument is specified by an IO like object (which responds
279
- # to <code>read</code>), a string, or a GPGME::Data object.
280
- #
281
- # An output argument is specified by an IO like object (which responds
282
- # to <code>write</code>) or a GPGME::Data object.
283
- #
284
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code> except for
285
- #
286
- # - <tt>:signers</tt> Signing keys. If specified, it is an array
287
- # whose elements are a GPGME::Key object or a string.
288
- #
289
- def GPGME.clearsign(plain, *args_options)
290
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 2
291
- args, options = split_args(args_options)
292
- args.push(options.merge({:mode => GPGME::SIG_MODE_CLEAR}))
293
- GPGME.sign(plain, *args)
294
- end
295
-
296
- # call-seq:
297
- # GPGME.detach_sign(plain, sig=nil, options=Hash.new)
298
- #
299
- # <code>GPGME.detach_sign</code> creates a detached signature of the plaintext.
300
- #
301
- # The arguments should be specified as follows.
302
- #
303
- # - GPGME.detach_sign(<i>plain</i>, <i>sig</i>, <i>options</i>)
304
- # - GPGME.detach_sign(<i>plain</i>, <i>options</i>) -> <i>sig</i>
305
- #
306
- # All arguments except <i>plain</i> are optional. <i>plain</i> is
307
- # input and <i>sig</i> is output. If the last argument is a Hash,
308
- # options will be read from it.
309
- #
310
- # An input argument is specified by an IO like object (which responds
311
- # to <code>read</code>), a string, or a GPGME::Data object.
312
- #
313
- # An output argument is specified by an IO like object (which responds
314
- # to <code>write</code>) or a GPGME::Data object.
315
- #
316
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code> except for
317
- #
318
- # - <tt>:signers</tt> Signing keys. If specified, it is an array
319
- # whose elements are a GPGME::Key object or a string.
320
- #
321
- def GPGME.detach_sign(plain, *args_options)
322
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 2
323
- args, options = split_args(args_options)
324
- args.push(options.merge({:mode => GPGME::SIG_MODE_DETACH}))
325
- GPGME.sign(plain, *args)
326
- end
327
-
328
- # call-seq:
329
- # GPGME.encrypt(recipients, plain, cipher=nil, options=Hash.new)
330
- #
331
- # <code>GPGME.encrypt</code> performs encryption.
332
- #
333
- # The arguments should be specified as follows.
334
- #
335
- # - GPGME.encrypt(<i>recipients</i>, <i>plain</i>, <i>cipher</i>, <i>options</i>)
336
- # - GPGME.encrypt(<i>recipients</i>, <i>plain</i>, <i>options</i>) -> <i>cipher</i>
337
- #
338
- # All arguments except <i>recipients</i> and <i>plain</i> are
339
- # optional. <i>plain</i> is input and <i>cipher</i> is output. If
340
- # the last argument is a Hash, options will be read from it.
341
- #
342
- # The recipients are specified by an array whose elements are a string
343
- # or a GPGME::Key object. If <i>recipients</i> is <tt>nil</tt>, it
344
- # performs symmetric encryption.
345
- #
346
- # An input argument is specified by an IO like object (which responds
347
- # to <code>read</code>), a string, or a GPGME::Data object.
348
- #
349
- # An output argument is specified by an IO like object (which responds
350
- # to <code>write</code>) or a GPGME::Data object.
351
- #
352
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code> except for
353
- #
354
- # - <tt>:sign</tt> If <tt>true</tt>, it performs a combined sign and
355
- # encrypt operation.
356
- # - <tt>:signers</tt> Signing keys. If specified, it is an array
357
- # whose elements are a GPGME::Key object or a string.
358
- # - <tt>:always_trust</tt> Setting this to <tt>true</tt> specifies all
359
- # the recipients should be trusted.
360
- #
361
- def GPGME.encrypt(recipients, plain, *args_options)
362
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 3
363
- args, options = split_args(args_options)
364
- cipher = args[0]
365
- recipient_keys = recipients ? resolve_keys(recipients, false, [:encrypt]) : nil
366
-
367
- check_version(options)
368
- GPGME::Ctx.new(options) do |ctx|
369
- plain_data = input_data(plain)
370
- cipher_data = output_data(cipher)
371
- begin
372
- flags = 0
373
- if options[:always_trust]
374
- flags |= GPGME::ENCRYPT_ALWAYS_TRUST
375
- end
376
- if options[:sign]
377
- if options[:signers]
378
- ctx.add_signer(*resolve_keys(options[:signers], true, [:sign]))
379
- end
380
- ctx.encrypt_sign(recipient_keys, plain_data, cipher_data, flags)
381
- else
382
- ctx.encrypt(recipient_keys, plain_data, cipher_data, flags)
383
- end
384
- rescue GPGME::Error::UnusablePublicKey => exc
385
- exc.keys = ctx.encrypt_result.invalid_recipients
386
- raise exc
387
- rescue GPGME::Error::UnusableSecretKey => exc
388
- exc.keys = ctx.sign_result.invalid_signers
389
- raise exc
390
- end
391
-
392
- unless cipher
393
- cipher_data.seek(0, IO::SEEK_SET)
394
- cipher_data.read
395
- end
396
- end
397
- end
398
-
399
- # call-seq:
400
- # GPGME.list_keys(pattern=nil, secret_only=false, options=Hash.new){|key| ...}
401
- #
402
- # <code>GPGME.list_keys</code> iterates over the key ring.
403
- #
404
- # The arguments should be specified as follows.
405
- #
406
- # - GPGME.list_keys(<i>pattern</i>, <i>secret_only</i>, <i>options</i>)
407
- #
408
- # All arguments are optional. If the last argument is a Hash, options
409
- # will be read from it.
410
- #
411
- # <i>pattern</i> is a string or <tt>nil</tt>. If <i>pattern</i> is
412
- # <tt>nil</tt>, all available keys are returned. If
413
- # <i>secret_only</i> is <tt>true</tt>, the only secret keys are
414
- # returned.
415
- #
416
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code>.
417
- #
418
- def GPGME.list_keys(*args_options) # :yields: key
419
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 3
420
- args, options = split_args(args_options)
421
- pattern, secret_only = args
422
- check_version(options)
423
- GPGME::Ctx.new do |ctx|
424
- if block_given?
425
- ctx.each_key(pattern, secret_only || false) do |key|
426
- yield key
427
- end
428
- else
429
- ctx.keys(pattern, secret_only || false)
430
- end
431
- end
432
- end
433
-
434
- # call-seq:
435
- # GPGME.export(pattern)
436
- #
437
- # <code>GPGME.export</code> extracts public keys from the key ring.
438
- #
439
- # The arguments should be specified as follows.
440
- #
441
- # - GPGME.export(<i>pattern</i>, <i>options</i>) -> <i>keydata</i>
442
- # - GPGME.export(<i>pattern</i>, <i>keydata</i>, <i>options</i>)
443
- #
444
- # All arguments are optional. If the last argument is a Hash, options
445
- # will be read from it.
446
- #
447
- # <i>pattern</i> is a string or <tt>nil</tt>. If <i>pattern</i> is
448
- # <tt>nil</tt>, all available public keys are returned.
449
- # <i>keydata</i> is output.
450
- #
451
- # An output argument is specified by an IO like object (which responds
452
- # to <code>write</code>) or a GPGME::Data object.
453
- #
454
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code>.
455
- #
456
- def GPGME.export(*args_options)
457
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 2
458
- args, options = split_args(args_options)
459
- pattern, key = args[0]
460
- key_data = output_data(key)
461
- check_version(options)
462
- GPGME::Ctx.new(options) do |ctx|
463
- ctx.export_keys(pattern, key_data)
464
-
465
- unless key
466
- key_data.seek(0, IO::SEEK_SET)
467
- key_data.read
468
- end
469
- end
470
- end
471
-
472
- # call-seq:
473
- # GPGME.import(keydata)
474
- #
475
- # <code>GPGME.import</code> adds the keys to the key ring.
476
- #
477
- # The arguments should be specified as follows.
478
- #
479
- # - GPGME.import(<i>keydata</i>, <i>options</i>)
480
- #
481
- # All arguments are optional. If the last argument is a Hash, options
482
- # will be read from it.
483
- #
484
- # <i>keydata</i> is input.
485
- #
486
- # An input argument is specified by an IO like object (which responds
487
- # to <code>read</code>), a string, or a GPGME::Data object.
488
- #
489
- # <i>options</i> are same as <code>GPGME::Ctx.new()</code>.
490
- #
491
- def GPGME.import(*args_options)
492
- raise ArgumentError, 'wrong number of arguments' if args_options.length > 2
493
- args, options = split_args(args_options)
494
- key = args[0]
495
- key_data = input_data(key)
496
- check_version(options)
497
- GPGME::Ctx.new(options) do |ctx|
498
- ctx.import_keys(key_data)
499
- ctx.import_result
500
- end
501
- end
502
-
503
- module GPGME
504
- # :stopdoc:
505
- private
506
-
507
- def split_args(args_options)
508
- if args_options.length > 0 and args_options[-1].respond_to? :to_hash
509
- args = args_options[0 ... -1]
510
- options = args_options[-1].to_hash
511
- else
512
- args = args_options
513
- options = Hash.new
514
- end
515
- [args, options]
516
- end
517
- module_function :split_args
518
4
 
519
- def check_version(options = nil)
520
- version = nil
521
- if options.kind_of?(String)
522
- version = options
523
- elsif options.include?(:version)
524
- version = options[:version]
525
- end
526
- unless GPGME::gpgme_check_version(version)
527
- raise Error::InvalidVersion.new
528
- end
529
- end
530
- module_function :check_version
531
-
532
- def resolve_keys(keys_or_names, secret_only, purposes = Array.new)
533
- keys = Array.new
534
- keys_or_names.each do |key_or_name|
535
- if key_or_name.kind_of? Key
536
- keys << key_or_name
537
- elsif key_or_name.kind_of? String
538
- GPGME::Ctx.new do |ctx|
539
- key = ctx.keys(key_or_name, secret_only).find {|k|
540
- k.usable_for?(purposes)
541
- }
542
- keys << key if key
543
- end
544
- end
545
- end
546
- keys
547
- end
548
- module_function :resolve_keys
549
-
550
- def input_data(input)
551
- if input.kind_of? GPGME::Data
552
- input
553
- elsif input.respond_to? :to_str
554
- GPGME::Data.from_str(input.to_str)
555
- elsif input.respond_to? :read
556
- GPGME::Data.from_callbacks(IOCallbacks.new(input))
557
- else
558
- raise ArgumentError, input.inspect
559
- end
560
- end
561
- module_function :input_data
562
-
563
- def output_data(output)
564
- if output.kind_of? GPGME::Data
565
- output
566
- elsif output.respond_to? :write
567
- GPGME::Data.from_callbacks(IOCallbacks.new(output))
568
- elsif !output
569
- GPGME::Data.empty
570
- else
571
- raise ArgumentError, output.inspect
572
- end
573
- end
574
- module_function :output_data
575
-
576
- class IOCallbacks
577
- def initialize(io)
578
- @io = io
579
- end
580
-
581
- def read(hook, length)
582
- @io.read(length)
583
- end
584
-
585
- def write(hook, buffer, length)
586
- @io.write(buffer[0 .. length])
587
- end
588
-
589
- def seek(hook, offset, whence)
590
- return @io.pos if offset == 0 && whence == IO::SEEK_CUR
591
- @io.seek(offset, whence)
592
- @io.pos
593
- end
594
- end
5
+ # TODO without this call one can't GPGME::Ctx.new, find out why
6
+ GPGME::gpgme_check_version(nil)
595
7
 
596
- PROTOCOL_NAMES = {
597
- PROTOCOL_OpenPGP => :OpenPGP,
598
- PROTOCOL_CMS => :CMS
599
- }
600
-
601
- KEYLIST_MODE_NAMES = {
602
- KEYLIST_MODE_LOCAL => :local,
603
- KEYLIST_MODE_EXTERN => :extern,
604
- KEYLIST_MODE_SIGS => :sigs,
605
- KEYLIST_MODE_VALIDATE => :validate
606
- }
607
-
608
- VALIDITY_NAMES = {
609
- VALIDITY_UNKNOWN => :unknown,
610
- VALIDITY_UNDEFINED => :undefined,
611
- VALIDITY_NEVER => :never,
612
- VALIDITY_MARGINAL => :marginal,
613
- VALIDITY_FULL => :full,
614
- VALIDITY_ULTIMATE => :ultimate
615
- }
616
- # :startdoc:
617
- end
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'
618
22
 
619
23
  module GPGME
620
- class Error < StandardError
621
- def initialize(error)
622
- @error = error
623
- end
624
- attr_reader :error
625
-
626
- # Return the error code.
627
- #
628
- # The error code indicates the type of an error, or the reason why
629
- # an operation failed.
630
- def code
631
- GPGME::gpgme_err_code(@error)
632
- end
633
-
634
- # Return the error source.
635
- #
636
- # The error source has not a precisely defined meaning. Sometimes
637
- # it is the place where the error happened, sometimes it is the
638
- # place where an error was encoded into an error value. Usually
639
- # the error source will give an indication to where to look for
640
- # the problem. This is not always true, but it is attempted to
641
- # achieve this goal.
642
- def source
643
- GPGME::gpgme_err_source(@error)
644
- end
645
-
646
- # Return a description of the error code.
647
- def message
648
- GPGME::gpgme_strerror(@error)
649
- end
650
-
651
- class General < self; end
652
- class InvalidValue < self; end
653
- class UnusablePublicKey < self
654
- attr_accessor :keys
655
- end
656
- class UnusableSecretKey < self
657
- attr_accessor :keys
658
- end
659
- class NoData < self; end
660
- class Conflict < self; end
661
- class NotImplemented < self; end
662
- class DecryptFailed < self; end
663
- class BadPassphrase < self; end
664
- class Canceled < self; end
665
- class InvalidEngine < self; end
666
- class AmbiguousName < self; end
667
- class WrongKeyUsage < self
668
- attr_accessor :key_usage
669
- end
670
- class CertificateRevoked < self; end
671
- class CertificateExpired < self; end
672
- class NoCRLKnown < self; end
673
- class NoPolicyMatch < self; end
674
- class NoSecretKey < self; end
675
- class MissingCertificate < self; end
676
- class BadCertificateChain < self; end
677
- class UnsupportedAlgorithm < self
678
- attr_accessor :algorithm
679
- end
680
- class BadSignature < self; end
681
- class NoPublicKey < self; end
682
- class InvalidVersion < self; end
683
- end
684
-
685
- def error_to_exception(err) # :nodoc:
686
- case GPGME::gpgme_err_code(err)
687
- when GPG_ERR_EOF
688
- EOFError.new
689
- when GPG_ERR_NO_ERROR
690
- nil
691
- when GPG_ERR_GENERAL
692
- Error::General.new(err)
693
- when GPG_ERR_ENOMEM
694
- Errno::ENOMEM.new
695
- when GPG_ERR_INV_VALUE
696
- Error::InvalidValue.new(err)
697
- when GPG_ERR_UNUSABLE_PUBKEY
698
- Error::UnusablePublicKey.new(err)
699
- when GPG_ERR_UNUSABLE_SECKEY
700
- Error::UnusableSecretKey.new(err)
701
- when GPG_ERR_NO_DATA
702
- Error::NoData.new(err)
703
- when GPG_ERR_CONFLICT
704
- Error::Conflict.new(err)
705
- when GPG_ERR_NOT_IMPLEMENTED
706
- Error::NotImplemented.new(err)
707
- when GPG_ERR_DECRYPT_FAILED
708
- Error::DecryptFailed.new(err)
709
- when GPG_ERR_BAD_PASSPHRASE
710
- Error::BadPassphrase.new(err)
711
- when GPG_ERR_CANCELED
712
- Error::Canceled.new(err)
713
- when GPG_ERR_INV_ENGINE
714
- Error::InvalidEngine.new(err)
715
- when GPG_ERR_AMBIGUOUS_NAME
716
- Error::AmbiguousName.new(err)
717
- when GPG_ERR_WRONG_KEY_USAGE
718
- Error::WrongKeyUsage.new(err)
719
- when GPG_ERR_CERT_REVOKED
720
- Error::CertificateRevoked.new(err)
721
- when GPG_ERR_CERT_EXPIRED
722
- Error::CertificateExpired.new(err)
723
- when GPG_ERR_NO_CRL_KNOWN
724
- Error::NoCRLKnown.new(err)
725
- when GPG_ERR_NO_POLICY_MATCH
726
- Error::NoPolicyMatch.new(err)
727
- when GPG_ERR_NO_SECKEY
728
- Error::NoSecretKey.new(err)
729
- when GPG_ERR_MISSING_CERT
730
- Error::MissingCertificate.new(err)
731
- when GPG_ERR_BAD_CERT_CHAIN
732
- Error::BadCertificateChain.new(err)
733
- when GPG_ERR_UNSUPPORTED_ALGORITHM
734
- Error::UnsupportedAlgorithm.new(err)
735
- when GPG_ERR_BAD_SIGNATURE
736
- Error::BadSignature.new(err)
737
- when GPG_ERR_NO_PUBKEY
738
- Error::NoPublicKey.new(err)
739
- else
740
- Error.new(err)
741
- end
742
- end
743
- module_function :error_to_exception
744
- private :error_to_exception
745
-
746
24
  class << self
25
+
26
+ # From the c extension
747
27
  alias pubkey_algo_name gpgme_pubkey_algo_name
748
28
  alias hash_algo_name gpgme_hash_algo_name
749
- end
750
-
751
- # Verify that the engine implementing the protocol <i>proto</i> is
752
- # installed in the system.
753
- def engine_check_version(proto)
754
- err = GPGME::gpgme_engine_check_version(proto)
755
- exc = GPGME::error_to_exception(err)
756
- raise exc if exc
757
- end
758
- module_function :engine_check_version
759
-
760
- # Return a list of info structures of enabled engines.
761
- def engine_info
762
- rinfo = Array.new
763
- GPGME::gpgme_get_engine_info(rinfo)
764
- rinfo
765
- end
766
- module_function :engine_info
767
-
768
- # Change the default configuration of the crypto engine implementing
769
- # protocol <i>proto</i>.
770
- #
771
- # <i>file_name</i> is the file name of the executable program
772
- # implementing the protocol.
773
- # <i>home_dir</i> is the directory name of the configuration directory.
774
- def set_engine_info(proto, file_name, home_dir)
775
- err = GPGME::gpgme_set_engine_info(proto, file_name, home_dir)
776
- exc = GPGME::error_to_exception(err)
777
- raise exc if exc
778
- end
779
- module_function :set_engine_info
780
-
781
- # A class for managing data buffers.
782
- class Data
783
- BLOCK_SIZE = 4096
784
-
785
- # Create a new instance.
786
- #
787
- # The created data types depend on <i>arg</i>. If <i>arg</i> is
788
- # <tt>nil</tt>, it creates an instance with an empty buffer.
789
- # Otherwise, <i>arg</i> is either a string, an IO, or a Pathname.
790
- def self.new(arg = nil, copy = false)
791
- if arg.nil?
792
- return empty
793
- elsif arg.respond_to? :to_str
794
- return from_str(arg.to_str, copy)
795
- elsif arg.respond_to? :to_io
796
- return from_io(arg.to_io)
797
- elsif arg.respond_to? :open
798
- return from_io(arg.open)
799
- end
800
- end
801
-
802
- # Create a new instance with an empty buffer.
803
- def self.empty
804
- rdh = Array.new
805
- err = GPGME::gpgme_data_new(rdh)
806
- exc = GPGME::error_to_exception(err)
807
- raise exc if exc
808
- rdh[0]
809
- end
810
-
811
- # Create a new instance with internal buffer.
812
- def self.from_str(buf, copy = true)
813
- rdh = Array.new
814
- err = GPGME::gpgme_data_new_from_mem(rdh, buf, buf.length)
815
- exc = GPGME::error_to_exception(err)
816
- raise exc if exc
817
- rdh[0]
818
- end
819
-
820
- # Create a new instance associated with a given IO.
821
- def self.from_io(io)
822
- from_callbacks(IOCallbacks.new(arg))
823
- end
824
-
825
- # Create a new instance from the specified file descriptor.
826
- def self.from_fd(fd)
827
- rdh = Array.new
828
- err = GPGME::gpgme_data_new_from_fd(rdh, fd)
829
- exc = GPGME::error_to_exception(err)
830
- raise exc if exc
831
- rdh[0]
832
- end
833
-
834
- # Create a new instance from the specified callbacks.
835
- def self.from_callbacks(callbacks, hook_value = nil)
836
- rdh = Array.new
837
- err = GPGME::gpgme_data_new_from_cbs(rdh, callbacks, hook_value)
838
- exc = GPGME::error_to_exception(err)
839
- raise exc if exc
840
- rdh[0]
841
- end
842
29
 
843
- # Read at most <i>length</i> bytes from the data object, or to the end
844
- # of file if <i>length</i> is omitted or is <tt>nil</tt>.
845
- def read(length = nil)
846
- if length
847
- GPGME::gpgme_data_read(self, length)
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)
848
87
  else
849
- buf = String.new
850
- loop do
851
- s = GPGME::gpgme_data_read(self, BLOCK_SIZE)
852
- break unless s
853
- buf << s
854
- end
855
- buf
856
- end
857
- end
858
-
859
- # Seek to a given <i>offset</i> in the data object according to the
860
- # value of <i>whence</i>.
861
- def seek(offset, whence = IO::SEEK_SET)
862
- GPGME::gpgme_data_seek(self, offset, IO::SEEK_SET)
863
- end
864
-
865
- # Write <i>length</i> bytes from <i>buffer</i> into the data object.
866
- def write(buffer, length = buffer.length)
867
- GPGME::gpgme_data_write(self, buffer, length)
868
- end
869
-
870
- # Return the encoding of the underlying data.
871
- def encoding
872
- GPGME::gpgme_data_get_encoding(self)
873
- end
874
-
875
- # Set the encoding to a given <i>encoding</i> of the underlying
876
- # data object.
877
- def encoding=(encoding)
878
- err = GPGME::gpgme_data_set_encoding(self, encoding)
879
- exc = GPGME::error_to_exception(err)
880
- raise exc if exc
881
- encoding
882
- end
883
- end
884
-
885
- class EngineInfo
886
- private_class_method :new
887
-
888
- attr_reader :protocol, :file_name, :version, :req_version, :home_dir
889
- alias required_version req_version
890
- end
891
-
892
- # A context within which all cryptographic operations are performed.
893
- class Ctx
894
- # Create a new instance from the given <i>options</i>.
895
- # <i>options</i> is a Hash whose keys are
896
- #
897
- # * <tt>:protocol</tt> Either <tt>PROTOCOL_OpenPGP</tt> or
898
- # <tt>PROTOCOL_CMS</tt>.
899
- #
900
- # * <tt>:armor</tt> If <tt>true</tt>, the output should be ASCII armored.
901
- #
902
- # * <tt>:textmode</tt> If <tt>true</tt>, inform the recipient that the
903
- # input is text.
904
- #
905
- # * <tt>:keylist_mode</tt> Either
906
- # <tt>KEYLIST_MODE_LOCAL</tt>,
907
- # <tt>KEYLIST_MODE_EXTERN</tt>,
908
- # <tt>KEYLIST_MODE_SIGS</tt>, or
909
- # <tt>KEYLIST_MODE_VALIDATE</tt>.
910
- # * <tt>:passphrase_callback</tt> A callback function.
911
- # * <tt>:passphrase_callback_value</tt> An object passed to
912
- # passphrase_callback.
913
- # * <tt>:progress_callback</tt> A callback function.
914
- # * <tt>:progress_callback_value</tt> An object passed to
915
- # progress_callback.
916
- #
917
- def self.new(options = Hash.new)
918
- rctx = Array.new
919
- err = GPGME::gpgme_new(rctx)
920
- exc = GPGME::error_to_exception(err)
921
- raise exc if exc
922
- ctx = rctx[0]
923
- options.each_pair do |key, value|
924
- case key
925
- when :protocol
926
- ctx.protocol = value
927
- when :armor
928
- ctx.armor = value
929
- when :textmode
930
- ctx.textmode = value
931
- when :keylist_mode
932
- ctx.keylist_mode = value
933
- when :passphrase_callback
934
- ctx.set_passphrase_callback(value,
935
- options[:passphrase_callback_value])
936
- when :progress_callback
937
- ctx.set_progress_callback(value,
938
- options[:progress_callback_value])
939
- end
940
- end
941
- if block_given?
942
- begin
943
- yield ctx
944
- ensure
945
- GPGME::gpgme_release(ctx)
946
- end
947
- else
948
- ctx
949
- end
950
- end
951
-
952
- # Set the <i>protocol</i> used within this context.
953
- def protocol=(proto)
954
- err = GPGME::gpgme_set_protocol(self, proto)
955
- exc = GPGME::error_to_exception(err)
956
- raise exc if exc
957
- proto
958
- end
959
-
960
- # Return the protocol used within this context.
961
- def protocol
962
- GPGME::gpgme_get_protocol(self)
963
- end
964
-
965
- # Tell whether the output should be ASCII armored.
966
- def armor=(yes)
967
- GPGME::gpgme_set_armor(self, yes ? 1 : 0)
968
- yes
969
- end
970
-
971
- # Return true if the output is ASCII armored.
972
- def armor
973
- GPGME::gpgme_get_armor(self) == 1 ? true : false
974
- end
975
-
976
- # Tell whether canonical text mode should be used.
977
- def textmode=(yes)
978
- GPGME::gpgme_set_textmode(self, yes ? 1 : 0)
979
- yes
980
- end
981
-
982
- # Return true if canonical text mode is enabled.
983
- def textmode
984
- GPGME::gpgme_get_textmode(self) == 1 ? true : false
985
- end
986
-
987
- # Change the default behaviour of the key listing functions.
988
- def keylist_mode=(mode)
989
- GPGME::gpgme_set_keylist_mode(self, mode)
990
- mode
991
- end
992
-
993
- # Return the current key listing mode.
994
- def keylist_mode
995
- GPGME::gpgme_get_keylist_mode(self)
996
- end
997
-
998
- def inspect
999
- "#<#{self.class} protocol=#{PROTOCOL_NAMES[protocol] || protocol}, \
1000
- armor=#{armor}, textmode=#{textmode}, \
1001
- keylist_mode=#{KEYLIST_MODE_NAMES[keylist_mode]}>"
1002
- end
1003
-
1004
- # Set the passphrase callback with given hook value.
1005
- # <i>passfunc</i> should respond to <code>call</code> with 5 arguments.
1006
- #
1007
- # def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
1008
- # $stderr.write("Passphrase for #{uid_hint}: ")
1009
- # $stderr.flush
1010
- # begin
1011
- # system('stty -echo')
1012
- # io = IO.for_fd(fd, 'w')
1013
- # io.puts(gets)
1014
- # io.flush
1015
- # ensure
1016
- # (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
1017
- # system('stty echo')
1018
- # end
1019
- # $stderr.puts
1020
- # end
1021
- #
1022
- # ctx.set_passphrase_callback(method(:passfunc))
1023
- #
1024
- def set_passphrase_callback(passfunc, hook_value = nil)
1025
- GPGME::gpgme_set_passphrase_cb(self, passfunc, hook_value)
1026
- end
1027
- alias set_passphrase_cb set_passphrase_callback
1028
-
1029
- # Set the progress callback with given hook value.
1030
- # <i>progfunc</i> should respond to <code>call</code> with 5 arguments.
1031
- #
1032
- # def progfunc(hook, what, type, current, total)
1033
- # $stderr.write("#{what}: #{current}/#{total}\r")
1034
- # $stderr.flush
1035
- # end
1036
- #
1037
- # ctx.set_progress_callback(method(:progfunc))
1038
- #
1039
- def set_progress_callback(progfunc, hook_value = nil)
1040
- GPGME::gpgme_set_progress_cb(self, progfunc, hook_value)
1041
- end
1042
- alias set_progress_cb set_progress_callback
1043
-
1044
- # Initiate a key listing operation for given pattern.
1045
- # If <i>pattern</i> is <tt>nil</tt>, all available keys are
1046
- # returned. If <i>secret_only</i> is <tt>true</tt>, the only
1047
- # secret keys are returned.
1048
- def keylist_start(pattern = nil, secret_only = false)
1049
- err = GPGME::gpgme_op_keylist_start(self, pattern, secret_only ? 1 : 0)
1050
- exc = GPGME::error_to_exception(err)
1051
- raise exc if exc
1052
- end
1053
-
1054
- # Advance to the next key in the key listing operation.
1055
- def keylist_next
1056
- rkey = Array.new
1057
- err = GPGME::gpgme_op_keylist_next(self, rkey)
1058
- exc = GPGME::error_to_exception(err)
1059
- raise exc if exc
1060
- rkey[0]
1061
- end
1062
-
1063
- # End a pending key list operation.
1064
- def keylist_end
1065
- err = GPGME::gpgme_op_keylist_end(self)
1066
- exc = GPGME::error_to_exception(err)
1067
- raise exc if exc
1068
- end
1069
-
1070
- # Convenient method to iterate over keys.
1071
- # If <i>pattern</i> is <tt>nil</tt>, all available keys are
1072
- # returned. If <i>secret_only</i> is <tt>true</tt>, the only
1073
- # secret keys are returned.
1074
- def each_key(pattern = nil, secret_only = false, &block) # :yields: key
1075
- keylist_start(pattern, secret_only)
1076
- begin
1077
- loop do
1078
- yield keylist_next
1079
- end
1080
- keys
1081
- rescue EOFError
1082
- # The last key in the list has already been returned.
1083
- ensure
1084
- keylist_end
1085
- end
1086
- end
1087
- alias each_keys each_key
1088
-
1089
- def keys(pattern = nil, secret_only = nil)
1090
- keys = Array.new
1091
- each_key(pattern, secret_only) do |key|
1092
- keys << key
1093
- end
1094
- keys
1095
- end
1096
-
1097
- # Get the key with the <i>fingerprint</i>.
1098
- # If <i>secret</i> is <tt>true</tt>, secret key is returned.
1099
- def get_key(fingerprint, secret = false)
1100
- rkey = Array.new
1101
- err = GPGME::gpgme_get_key(self, fingerprint, rkey, secret ? 1 : 0)
1102
- exc = GPGME::error_to_exception(err)
1103
- raise exc if exc
1104
- rkey[0]
1105
- end
1106
-
1107
- # Generate a new key pair.
1108
- # <i>parms</i> is a string which looks like
1109
- #
1110
- # <GnupgKeyParms format="internal">
1111
- # Key-Type: DSA
1112
- # Key-Length: 1024
1113
- # Subkey-Type: ELG-E
1114
- # Subkey-Length: 1024
1115
- # Name-Real: Joe Tester
1116
- # Name-Comment: with stupid passphrase
1117
- # Name-Email: joe@foo.bar
1118
- # Expire-Date: 0
1119
- # Passphrase: abc
1120
- # </GnupgKeyParms>
1121
- #
1122
- # If <i>pubkey</i> and <i>seckey</i> are both set to <tt>nil</tt>,
1123
- # it stores the generated key pair into your key ring.
1124
- def generate_key(parms, pubkey = Data.new, seckey = Data.new)
1125
- err = GPGME::gpgme_op_genkey(self, parms, pubkey, seckey)
1126
- exc = GPGME::error_to_exception(err)
1127
- raise exc if exc
1128
- end
1129
- alias genkey generate_key
1130
-
1131
- # Extract the public keys of the recipients.
1132
- def export_keys(recipients, keydata = Data.new)
1133
- err = GPGME::gpgme_op_export(self, recipients, 0, keydata)
1134
- exc = GPGME::error_to_exception(err)
1135
- raise exc if exc
1136
- keydata
1137
- end
1138
- alias export export_keys
1139
-
1140
- # Add the keys in the data buffer to the key ring.
1141
- def import_keys(keydata)
1142
- err = GPGME::gpgme_op_import(self, keydata)
1143
- exc = GPGME::error_to_exception(err)
1144
- raise exc if exc
1145
- end
1146
- alias import import_keys
1147
-
1148
- def import_result
1149
- GPGME::gpgme_op_import_result(self)
1150
- end
1151
-
1152
- # Delete the key from the key ring.
1153
- # If allow_secret is false, only public keys are deleted,
1154
- # otherwise secret keys are deleted as well.
1155
- def delete_key(key, allow_secret = false)
1156
- err = GPGME::gpgme_op_delete(self, key, allow_secret ? 1 : 0)
1157
- exc = GPGME::error_to_exception(err)
1158
- raise exc if exc
1159
- end
1160
- alias delete delete_key
1161
-
1162
- # Edit attributes of the key in the local key ring.
1163
- def edit_key(key, editfunc, hook_value = nil, out = Data.new)
1164
- err = GPGME::gpgme_op_edit(self, key, editfunc, hook_value, out)
1165
- exc = GPGME::error_to_exception(err)
1166
- raise exc if exc
1167
- end
1168
- alias edit edit_key
1169
-
1170
- # Edit attributes of the key on the card.
1171
- def edit_card_key(key, editfunc, hook_value = nil, out = Data.new)
1172
- err = GPGME::gpgme_op_card_edit(self, key, editfunc, hook_value, out)
1173
- exc = GPGME::error_to_exception(err)
1174
- raise exc if exc
1175
- end
1176
- alias edit_card edit_card_key
1177
- alias card_edit edit_card_key
1178
-
1179
- # Decrypt the ciphertext and return the plaintext.
1180
- def decrypt(cipher, plain = Data.new)
1181
- err = GPGME::gpgme_op_decrypt(self, cipher, plain)
1182
- exc = GPGME::error_to_exception(err)
1183
- raise exc if exc
1184
- plain
1185
- end
1186
-
1187
- def decrypt_verify(cipher, plain = Data.new)
1188
- err = GPGME::gpgme_op_decrypt_verify(self, cipher, plain)
1189
- exc = GPGME::error_to_exception(err)
1190
- raise exc if exc
1191
- plain
1192
- end
1193
-
1194
- def decrypt_result
1195
- GPGME::gpgme_op_decrypt_result(self)
1196
- end
1197
-
1198
- # Verify that the signature in the data object is a valid signature.
1199
- def verify(sig, signed_text = nil, plain = Data.new)
1200
- err = GPGME::gpgme_op_verify(self, sig, signed_text, plain)
1201
- exc = GPGME::error_to_exception(err)
1202
- raise exc if exc
1203
- plain
1204
- end
1205
-
1206
- def verify_result
1207
- GPGME::gpgme_op_verify_result(self)
1208
- end
1209
-
1210
- # Decrypt the ciphertext and return the plaintext.
1211
- def decrypt_verify(cipher, plain = Data.new)
1212
- err = GPGME::gpgme_op_decrypt_verify(self, cipher, plain)
1213
- exc = GPGME::error_to_exception(err)
1214
- raise exc if exc
1215
- plain
1216
- end
1217
-
1218
- # Remove the list of signers from this object.
1219
- def clear_signers
1220
- GPGME::gpgme_signers_clear(self)
1221
- end
1222
-
1223
- # Add _keys_ to the list of signers.
1224
- def add_signer(*keys)
1225
- keys.each do |key|
1226
- err = GPGME::gpgme_signers_add(self, key)
1227
- exc = GPGME::error_to_exception(err)
1228
- raise exc if exc
1229
- end
1230
- end
1231
-
1232
- # Create a signature for the text.
1233
- # <i>plain</i> is a data object which contains the text.
1234
- # <i>sig</i> is a data object where the generated signature is stored.
1235
- def sign(plain, sig = Data.new, mode = GPGME::SIG_MODE_NORMAL)
1236
- err = GPGME::gpgme_op_sign(self, plain, sig, mode)
1237
- exc = GPGME::error_to_exception(err)
1238
- raise exc if exc
1239
- sig
1240
- end
1241
-
1242
- def sign_result
1243
- GPGME::gpgme_op_sign_result(self)
1244
- end
1245
-
1246
- # Encrypt the plaintext in the data object for the recipients and
1247
- # return the ciphertext.
1248
- def encrypt(recp, plain, cipher = Data.new, flags = 0)
1249
- err = GPGME::gpgme_op_encrypt(self, recp, flags, plain, cipher)
1250
- exc = GPGME::error_to_exception(err)
1251
- raise exc if exc
1252
- cipher
1253
- end
1254
-
1255
- def encrypt_result
1256
- GPGME::gpgme_op_encrypt_result(self)
1257
- end
1258
-
1259
- def encrypt_sign(recp, plain, cipher = Data.new, flags = 0)
1260
- err = GPGME::gpgme_op_encrypt_sign(self, recp, flags, plain, cipher)
1261
- exc = GPGME::error_to_exception(err)
1262
- raise exc if exc
1263
- cipher
1264
- end
1265
- end
1266
-
1267
- # A public or secret key.
1268
- class Key
1269
- private_class_method :new
1270
-
1271
- attr_reader :keylist_mode, :protocol, :owner_trust
1272
- attr_reader :issuer_serial, :issuer_name, :chain_id
1273
- attr_reader :subkeys, :uids
1274
-
1275
- def trust
1276
- return :revoked if @revoked == 1
1277
- return :expired if @expired == 1
1278
- return :disabled if @disabled == 1
1279
- return :invalid if @invalid == 1
1280
- end
1281
-
1282
- def capability
1283
- caps = Array.new
1284
- caps << :encrypt if @can_encrypt
1285
- caps << :sign if @can_sign
1286
- caps << :certify if @can_certify
1287
- caps << :authenticate if @can_authenticate
1288
- caps
1289
- end
1290
-
1291
- def usable_for?(purposes)
1292
- unless purposes.kind_of? Array
1293
- purposes = [purposes]
1294
- end
1295
- return false if [:revoked, :expired, :disabled, :invalid].include? trust
1296
- return (purposes - capability).empty?
1297
- end
1298
-
1299
- def secret?
1300
- @secret == 1
1301
- end
1302
-
1303
- def inspect
1304
- primary_subkey = subkeys[0]
1305
- sprintf("#<#{self.class} %s %4d%c/%s %s trust=%s, owner_trust=%s, \
1306
- capability=%s, subkeys=%s, uids=%s>",
1307
- primary_subkey.secret? ? 'sec' : 'pub',
1308
- primary_subkey.length,
1309
- primary_subkey.pubkey_algo_letter,
1310
- primary_subkey.fingerprint[-8 .. -1],
1311
- primary_subkey.timestamp.strftime('%Y-%m-%d'),
1312
- trust.inspect,
1313
- VALIDITY_NAMES[@owner_trust].inspect,
1314
- capability.inspect,
1315
- subkeys.inspect,
1316
- uids.inspect)
1317
- end
1318
-
1319
- def to_s
1320
- primary_subkey = subkeys[0]
1321
- s = sprintf("%s %4d%c/%s %s\n",
1322
- primary_subkey.secret? ? 'sec' : 'pub',
1323
- primary_subkey.length,
1324
- primary_subkey.pubkey_algo_letter,
1325
- primary_subkey.fingerprint[-8 .. -1],
1326
- primary_subkey.timestamp.strftime('%Y-%m-%d'))
1327
- uids.each do |user_id|
1328
- s << "uid\t\t#{user_id.name} <#{user_id.email}>\n"
1329
- end
1330
- subkeys.each do |subkey|
1331
- s << subkey.to_s
1332
- end
1333
- s
1334
- end
1335
- end
1336
-
1337
- class SubKey
1338
- private_class_method :new
1339
-
1340
- attr_reader :pubkey_algo, :length, :keyid, :fpr
1341
- alias fingerprint fpr
1342
-
1343
- def trust
1344
- return :revoked if @revoked == 1
1345
- return :expired if @expired == 1
1346
- return :disabled if @disabled == 1
1347
- return :invalid if @invalid == 1
1348
- end
1349
-
1350
- def capability
1351
- caps = Array.new
1352
- caps << :encrypt if @can_encrypt
1353
- caps << :sign if @can_sign
1354
- caps << :certify if @can_certify
1355
- caps << :authenticate if @can_authenticate
1356
- caps
1357
- end
1358
-
1359
- def usable_for?(purposes)
1360
- unless purposes.kind_of? Array
1361
- purposes = [purposes]
88
+ Error.new(err)
1362
89
  end
1363
- return false if [:revoked, :expired, :disabled, :invalid].include? trust
1364
- return (purposes - capability).empty?
1365
- end
1366
-
1367
- def secret?
1368
- @secret == 1
1369
- end
1370
-
1371
- def timestamp
1372
- Time.at(@timestamp)
1373
- end
1374
-
1375
- def expires
1376
- Time.at(@expires)
1377
- end
1378
-
1379
- PUBKEY_ALGO_LETTERS = {
1380
- PK_RSA => ?R,
1381
- PK_ELG_E => ?g,
1382
- PK_ELG => ?G,
1383
- PK_DSA => ?D
1384
- }
1385
-
1386
- def pubkey_algo_letter
1387
- PUBKEY_ALGO_LETTERS[@pubkey_algo] || ??
1388
- end
1389
-
1390
- def inspect
1391
- sprintf("#<#{self.class} %s %4d%c/%s %s trust=%s, capability=%s>",
1392
- secret? ? 'ssc' : 'sub',
1393
- length,
1394
- pubkey_algo_letter,
1395
- (@fingerprint || @keyid)[-8 .. -1],
1396
- timestamp.strftime('%Y-%m-%d'),
1397
- trust.inspect,
1398
- capability.inspect)
1399
- end
1400
-
1401
- def to_s
1402
- sprintf("%s %4d%c/%s %s\n",
1403
- secret? ? 'ssc' : 'sub',
1404
- length,
1405
- pubkey_algo_letter,
1406
- (@fingerprint || @keyid)[-8 .. -1],
1407
- timestamp.strftime('%Y-%m-%d'))
1408
- end
1409
- end
1410
-
1411
- class UserID
1412
- private_class_method :new
1413
-
1414
- attr_reader :validity, :uid, :name, :comment, :email, :signatures
1415
-
1416
- def revoked?
1417
- @revoked == 1
1418
- end
1419
-
1420
- def invalid?
1421
- @invalid == 1
1422
- end
1423
-
1424
- def inspect
1425
- "#<#{self.class} #{name} <#{email}> \
1426
- validity=#{VALIDITY_NAMES[validity]}, signatures=#{signatures.inspect}>"
1427
- end
1428
- end
1429
-
1430
- class KeySig
1431
- private_class_method :new
1432
-
1433
- attr_reader :pubkey_algo, :keyid
1434
-
1435
- def revoked?
1436
- @revoked == 1
1437
- end
1438
-
1439
- def expired?
1440
- @expired == 1
1441
90
  end
1442
91
 
1443
- def invalid?
1444
- @invalid == 1
1445
- end
1446
-
1447
- def exportable?
1448
- @exportable == 1
1449
- end
1450
-
1451
- def timestamp
1452
- Time.at(@timestamp)
1453
- end
1454
-
1455
- def expires
1456
- Time.at(@expires)
1457
- end
1458
-
1459
- def inspect
1460
- "#<#{self.class} #{keyid} timestamp=#{timestamp}, expires=#{expires}>"
1461
- end
1462
- end
1463
-
1464
- class VerifyResult
1465
- private_class_method :new
1466
-
1467
- attr_reader :signatures
1468
- end
1469
-
1470
- class Signature
1471
- private_class_method :new
1472
-
1473
- attr_reader :summary, :fpr, :status, :notations, :wrong_key_usage
1474
- attr_reader :validity, :validity_reason
1475
- attr_reader :pka_trust, :pka_address
1476
- alias fingerprint fpr
1477
-
1478
- def timestamp
1479
- Time.at(@timestamp)
1480
- end
1481
-
1482
- def exp_timestamp
1483
- Time.at(@exp_timestamp)
1484
- end
1485
-
1486
- def to_s
1487
- ctx = Ctx.new
1488
- if from_key = ctx.get_key(fingerprint)
1489
- from = "#{from_key.subkeys[0].keyid} #{from_key.uids[0].uid}"
1490
- else
1491
- from = fingerprint
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]
1492
101
  end
1493
- case GPGME::gpgme_err_code(status)
1494
- when GPGME::GPG_ERR_NO_ERROR
1495
- "Good signature from #{from}"
1496
- when GPGME::GPG_ERR_SIG_EXPIRED
1497
- "Expired signature from #{from}"
1498
- when GPGME::GPG_ERR_KEY_EXPIRED
1499
- "Signature made from expired key #{from}"
1500
- when GPGME::GPG_ERR_CERT_REVOKED
1501
- "Signature made from revoked key #{from}"
1502
- when GPGME::GPG_ERR_BAD_SIGNATURE
1503
- "Bad signature from #{from}"
1504
- when GPGME::GPG_ERR_NO_ERROR
1505
- "No public key for #{from}"
102
+ unless GPGME::gpgme_check_version(version)
103
+ raise Error::InvalidVersion.new
1506
104
  end
1507
105
  end
1508
- end
1509
-
1510
- class DecryptResult
1511
- private_class_method :new
1512
-
1513
- attr_reader :unsupported_algorithm, :wrong_key_usage
1514
- end
1515
-
1516
- class SignResult
1517
- private_class_method :new
1518
-
1519
- attr_reader :invalid_signers, :signatures
1520
- end
1521
-
1522
- class EncryptResult
1523
- private_class_method :new
1524
-
1525
- attr_reader :invalid_recipients
1526
- end
1527
-
1528
- class InvalidKey
1529
- private_class_method :new
1530
-
1531
- attr_reader :fpr, :reason
1532
- alias fingerprint fpr
1533
- end
1534
-
1535
- class NewSignature
1536
- private_class_method :new
1537
-
1538
- attr_reader :type, :pubkey_algo, :hash_algo, :sig_class, :fpr
1539
- alias fingerprint fpr
1540
-
1541
- def timestamp
1542
- Time.at(@timestamp)
1543
- end
1544
- end
1545
-
1546
- class ImportStatus
1547
- private_class_method :new
1548
-
1549
- attr_reader :fpr, :result, :status
1550
- alias fingerprint fpr
1551
- end
1552
-
1553
- class ImportResult
1554
- private_class_method :new
1555
106
 
1556
- attr_reader :considered, :no_user_id, :imported, :imported_rsa, :unchanged
1557
- attr_reader :new_user_ids, :new_sub_keys, :new_signatures, :new_revocations
1558
- attr_reader :secret_read, :secret_imported, :secret_unchanged
1559
- attr_reader :not_imported, :imports
1560
107
  end
1561
108
  end