gpgme-ffi 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/edit.rb +77 -0
- data/examples/genkey.rb +55 -0
- data/examples/keylist.rb +7 -0
- data/examples/roundtrip.rb +42 -0
- data/examples/sign.rb +31 -0
- data/examples/verify.rb +8 -0
- data/ext/gpgme/Makefile.in +55 -0
- data/ext/gpgme/extconf.rb +8 -0
- data/ext/gpgme/extract_enums.rb +88 -0
- data/ext/gpgme/gpgme-1.3.1.tar.bz2 +0 -0
- data/ext/gpgme/libassuan-2.0.2.tar.bz2 +0 -0
- data/ext/gpgme/libgpg-error-1.10.tar.bz2 +0 -0
- data/ext/gpgme/libgpgme_gem.so +0 -0
- data/lib/gpgme/compat.rb +48 -0
- data/lib/gpgme/constants.rb +187 -0
- data/lib/gpgme/crypto.rb +357 -0
- data/lib/gpgme/ctx.rb +462 -0
- data/lib/gpgme/data.rb +189 -0
- data/lib/gpgme/engine.rb +76 -0
- data/lib/gpgme/error.rb +66 -0
- data/lib/gpgme/ffi/ctx.rb +36 -0
- data/lib/gpgme/ffi/data.rb +24 -0
- data/lib/gpgme/ffi/decrypt_result.rb +14 -0
- data/lib/gpgme/ffi/encrypt_result.rb +22 -0
- data/lib/gpgme/ffi/engine_info.rb +17 -0
- data/lib/gpgme/ffi/enums.rb +687 -0
- data/lib/gpgme/ffi/functions.rb +364 -0
- data/lib/gpgme/ffi/import_result.rb +35 -0
- data/lib/gpgme/ffi/import_status.rb +15 -0
- data/lib/gpgme/ffi/invalid_key.rb +14 -0
- data/lib/gpgme/ffi/key.rb +60 -0
- data/lib/gpgme/ffi/key_sig.rb +20 -0
- data/lib/gpgme/ffi/library.rb +279 -0
- data/lib/gpgme/ffi/meta.rb +57 -0
- data/lib/gpgme/ffi/new_signature.rb +18 -0
- data/lib/gpgme/ffi/sig_notation.rb +12 -0
- data/lib/gpgme/ffi/sign_result.rb +33 -0
- data/lib/gpgme/ffi/signature.rb +35 -0
- data/lib/gpgme/ffi/sub_key.rb +27 -0
- data/lib/gpgme/ffi/trust_item.rb +31 -0
- data/lib/gpgme/ffi/user_id.rb +30 -0
- data/lib/gpgme/ffi/verify_result.rb +22 -0
- data/lib/gpgme/ffi.rb +22 -0
- data/lib/gpgme/io_callbacks.rb +21 -0
- data/lib/gpgme/key.rb +242 -0
- data/lib/gpgme/key_common.rb +43 -0
- data/lib/gpgme/key_sig.rb +35 -0
- data/lib/gpgme/misc.rb +66 -0
- data/lib/gpgme/signature.rb +85 -0
- data/lib/gpgme/sub_key.rb +58 -0
- data/lib/gpgme/user_id.rb +20 -0
- data/lib/gpgme/version.rb +3 -0
- data/lib/gpgme.rb +106 -0
- data/test/crypto_test.rb +246 -0
- data/test/ctx_test.rb +432 -0
- data/test/data_test.rb +129 -0
- data/test/files/testkey_pub.gpg +52 -0
- data/test/files/testkey_sec.gpg +54 -0
- data/test/gpgme_test.rb +12 -0
- data/test/key_test.rb +209 -0
- data/test/signature_test.rb +52 -0
- data/test/sub_key_test.rb +48 -0
- data/test/support/resources.rb +516 -0
- data/test/test_helper.rb +84 -0
- metadata +203 -0
data/lib/gpgme/key.rb
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
module GPGME
|
2
|
+
|
3
|
+
##
|
4
|
+
# A ruby representation of a public or a secret key.
|
5
|
+
#
|
6
|
+
# Every key has two instances of {GPGME::SubKey}, accessible through
|
7
|
+
# {.subkeys}, and with a {.primary_subkey} where most attributes are
|
8
|
+
# derived from, like the +fingerprint+.
|
9
|
+
#
|
10
|
+
# Also, every key has at least a {GPGME::UserID}, accessible through
|
11
|
+
# {.uids}, with a {.primary_uid}, where other attributes are derived from,
|
12
|
+
# like +email+ or +name+
|
13
|
+
class Key
|
14
|
+
private_class_method :new
|
15
|
+
|
16
|
+
attr_reader :keylist_mode, :protocol, :owner_trust
|
17
|
+
attr_reader :issuer_serial, :issuer_name, :chain_id
|
18
|
+
attr_reader :subkeys, :uids
|
19
|
+
|
20
|
+
include KeyCommon
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
##
|
25
|
+
# Returns an array of {GPGME::Key} objects that match the parameters.
|
26
|
+
# * +secret+ set to +:secret+ to get only secret keys, or to +:public+ to
|
27
|
+
# get only public keys.
|
28
|
+
# * +keys_or_names+ an array or an item that can be either {GPGME::Key}
|
29
|
+
# elements, or string identifiers like the email or the sha. Leave
|
30
|
+
# blank to get all.
|
31
|
+
# * +purposes+ get only keys that are usable for any of these purposes.
|
32
|
+
# See {GPGME::Key} for a list of possible key capabilities.
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# GPGME::Key.find :secret # => first secret key found
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# GPGME::Key.find(:public, "mrsimo@example.com")
|
39
|
+
# # => return only public keys that match mrsimo@example.com
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# GPGME::Key.find(:public, "mrsimo@example.com", :sign)
|
43
|
+
# # => return the public keys that match mrsimo@example.com and are
|
44
|
+
# # capable of signing
|
45
|
+
def find(secret, keys_or_names = nil, purposes = [])
|
46
|
+
secret = (secret == :secret)
|
47
|
+
keys_or_names = [""] if keys_or_names.nil? || (keys_or_names.is_a?(Array) && keys_or_names.empty?)
|
48
|
+
keys_or_names = [keys_or_names].flatten
|
49
|
+
purposes = [purposes].flatten.compact.uniq
|
50
|
+
|
51
|
+
keys = []
|
52
|
+
keys_or_names.each do |key_or_name|
|
53
|
+
case key_or_name
|
54
|
+
when Key then keys << key_or_name
|
55
|
+
when String
|
56
|
+
GPGME::Ctx.new do |ctx|
|
57
|
+
keys += ctx.keys(key_or_name, secret).select do |k|
|
58
|
+
k.usable_for?(purposes)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
keys
|
64
|
+
end
|
65
|
+
|
66
|
+
def get(fingerprint)
|
67
|
+
Ctx.new do |ctx|
|
68
|
+
ctx.get_key(fingerprint)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Exports public keys
|
73
|
+
#
|
74
|
+
# GPGME::Key.export pattern, options
|
75
|
+
#
|
76
|
+
# Private keys cannot be exported due to GPGME restrictions.
|
77
|
+
#
|
78
|
+
# @param pattern
|
79
|
+
# Identifier of the key to export.
|
80
|
+
#
|
81
|
+
# @param [Hash] options
|
82
|
+
# * +:output+ specify where to write the key to. It will be converted to
|
83
|
+
# a {GPGME::Data}, so it could be a file, for example.
|
84
|
+
# * Any other option accepted by {GPGME::Ctx.new}
|
85
|
+
#
|
86
|
+
# @return [GPGME::Data] the exported key.
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# key = GPGME::Key.export "mrsimo@example.com"
|
90
|
+
#
|
91
|
+
# @example writing to a file
|
92
|
+
# out = File.open("my.key", "w+")
|
93
|
+
# GPGME::Key.export "mrsimo@example.com", :output => out
|
94
|
+
#
|
95
|
+
def export(pattern, options = {})
|
96
|
+
output = Data.new(options[:output])
|
97
|
+
|
98
|
+
GPGME::Ctx.new(options) do |ctx|
|
99
|
+
ctx.export_keys(pattern, output)
|
100
|
+
end
|
101
|
+
|
102
|
+
output.seek(0)
|
103
|
+
output
|
104
|
+
end
|
105
|
+
|
106
|
+
# Imports a key
|
107
|
+
#
|
108
|
+
# GPGME::Key.import keydata, options
|
109
|
+
#
|
110
|
+
# @param keydata
|
111
|
+
# The key to import. It will be converted to a {GPGME::Data} object,
|
112
|
+
# so could be a file, for example.
|
113
|
+
# @param options
|
114
|
+
# Any other option accepted by {GPGME::Ctx.new}
|
115
|
+
#
|
116
|
+
# @example
|
117
|
+
# GPGME::Key.import(File.open("my.key"))
|
118
|
+
#
|
119
|
+
def import(keydata, options = {})
|
120
|
+
GPGME::Ctx.new(options) do |ctx|
|
121
|
+
ctx.import_keys(Data.new(keydata))
|
122
|
+
ctx.import_result
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
##
|
128
|
+
# Exports this key. Accepts the same options as {GPGME::Ctx.new}, and
|
129
|
+
# +options[:output]+, where you can specify something that can become a
|
130
|
+
# {GPGME::Data}, where the output will go.
|
131
|
+
#
|
132
|
+
# @example
|
133
|
+
# key.export(:armor => true)
|
134
|
+
# # => GPGME::Data you can read with ASCII armored format
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
# file = File.open("key.asc", "w+")
|
138
|
+
# key.export(:output => file)
|
139
|
+
# # => the key will be written to the file.
|
140
|
+
#
|
141
|
+
def export(options = {})
|
142
|
+
Key.export self.sha, options
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# Delete this key. If it's public, and has a secret one it will fail unless
|
147
|
+
# +allow_secret+ is specified as true.
|
148
|
+
def delete!(allow_secret = false)
|
149
|
+
GPGME::Ctx.new do |ctx|
|
150
|
+
ctx.delete_key self, allow_secret
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# Returns the expiry date for this key
|
156
|
+
def expires
|
157
|
+
primary_subkey.expires
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# Returns true if the key is expired
|
162
|
+
def expired
|
163
|
+
subkeys.any?(&:expired)
|
164
|
+
end
|
165
|
+
|
166
|
+
def primary_subkey
|
167
|
+
@primary_subkey ||= subkeys.first
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# Short descriptive value. Can be used to identify the key.
|
172
|
+
def sha
|
173
|
+
primary_subkey.sha
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# Longer descriptive value. Can be used to identify the key.
|
178
|
+
def fingerprint
|
179
|
+
primary_subkey.fingerprint
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
# Returns the main {GPGME::UserID} for this key.
|
184
|
+
def primary_uid
|
185
|
+
uids.first
|
186
|
+
end
|
187
|
+
|
188
|
+
##
|
189
|
+
# Returns the email for this key.
|
190
|
+
def email
|
191
|
+
primary_uid.email
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
# Returns the issuer name for this key.
|
196
|
+
def name
|
197
|
+
primary_uid.name
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# Returns the issuer comment for this key.
|
202
|
+
def comment
|
203
|
+
primary_uid.comment
|
204
|
+
end
|
205
|
+
|
206
|
+
def ==(another_key)
|
207
|
+
self.class === another_key and fingerprint == another_key.fingerprint
|
208
|
+
end
|
209
|
+
|
210
|
+
def inspect
|
211
|
+
sprintf("#<#{self.class} %s %4d%s/%s %s trust=%s, owner_trust=%s, \
|
212
|
+
capability=%s, subkeys=%s, uids=%s>",
|
213
|
+
primary_subkey.secret? ? 'sec' : 'pub',
|
214
|
+
primary_subkey.length,
|
215
|
+
primary_subkey.pubkey_algo_letter,
|
216
|
+
primary_subkey.fingerprint[-8 .. -1],
|
217
|
+
primary_subkey.timestamp.strftime('%Y-%m-%d'),
|
218
|
+
trust.inspect,
|
219
|
+
VALIDITY_NAMES[@owner_trust].inspect,
|
220
|
+
capability.inspect,
|
221
|
+
subkeys.inspect,
|
222
|
+
uids.inspect)
|
223
|
+
end
|
224
|
+
|
225
|
+
def to_s
|
226
|
+
primary_subkey = subkeys[0]
|
227
|
+
s = sprintf("%s %4d%s/%s %s\n",
|
228
|
+
primary_subkey.secret? ? 'sec' : 'pub',
|
229
|
+
primary_subkey.length,
|
230
|
+
primary_subkey.pubkey_algo_letter,
|
231
|
+
primary_subkey.fingerprint[-8 .. -1],
|
232
|
+
primary_subkey.timestamp.strftime('%Y-%m-%d'))
|
233
|
+
uids.each do |user_id|
|
234
|
+
s << "uid\t\t#{user_id.name} <#{user_id.email}>\n"
|
235
|
+
end
|
236
|
+
subkeys.each do |subkey|
|
237
|
+
s << subkey.to_s
|
238
|
+
end
|
239
|
+
s
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module GPGME
|
2
|
+
module KeyCommon
|
3
|
+
|
4
|
+
##
|
5
|
+
# Returns nil if the trust is valid.
|
6
|
+
# Returns one of +:revoked+, +:expired+, +:disabled+, +:invalid+
|
7
|
+
def trust
|
8
|
+
return :revoked if @revoked == 1
|
9
|
+
return :expired if @expired == 1
|
10
|
+
return :disabled if @disabled == 1
|
11
|
+
return :invalid if @invalid == 1
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Array of capabilities for this key. It can contain any combination of
|
16
|
+
# +:encrypt+, +:sign+, +:certify+ or +:authenticate+
|
17
|
+
def capability
|
18
|
+
caps = []
|
19
|
+
caps << :encrypt if @can_encrypt
|
20
|
+
caps << :sign if @can_sign
|
21
|
+
caps << :certify if @can_certify
|
22
|
+
caps << :authenticate if @can_authenticate
|
23
|
+
caps
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Checks if the key is capable of all of these actions. If empty array
|
28
|
+
# is passed then will return true.
|
29
|
+
#
|
30
|
+
# Returns false if the keys trust has been invalidated.
|
31
|
+
def usable_for?(purposes)
|
32
|
+
unless purposes.kind_of? Array
|
33
|
+
purposes = [purposes]
|
34
|
+
end
|
35
|
+
return false if [:revoked, :expired, :disabled, :invalid].include? trust
|
36
|
+
return (purposes - capability).empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def secret?
|
40
|
+
@secret == 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module GPGME
|
2
|
+
class KeySig
|
3
|
+
private_class_method :new
|
4
|
+
|
5
|
+
attr_reader :pubkey_algo, :keyid
|
6
|
+
|
7
|
+
def revoked?
|
8
|
+
@revoked == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def expired?
|
12
|
+
@expired == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
def invalid?
|
16
|
+
@invalid == 1
|
17
|
+
end
|
18
|
+
|
19
|
+
def exportable?
|
20
|
+
@exportable == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def timestamp
|
24
|
+
Time.at(@timestamp)
|
25
|
+
end
|
26
|
+
|
27
|
+
def expires
|
28
|
+
Time.at(@expires)
|
29
|
+
end
|
30
|
+
|
31
|
+
def inspect
|
32
|
+
"#<#{self.class} #{keyid} timestamp=#{timestamp}, expires=#{expires}>"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/gpgme/misc.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module GPGME
|
2
|
+
class EngineInfo
|
3
|
+
private_class_method :new
|
4
|
+
|
5
|
+
attr_reader :protocol, :file_name, :version, :req_version, :home_dir
|
6
|
+
alias required_version req_version
|
7
|
+
end
|
8
|
+
|
9
|
+
class VerifyResult
|
10
|
+
private_class_method :new
|
11
|
+
|
12
|
+
attr_reader :signatures
|
13
|
+
end
|
14
|
+
|
15
|
+
class DecryptResult
|
16
|
+
private_class_method :new
|
17
|
+
|
18
|
+
attr_reader :unsupported_algorithm, :wrong_key_usage
|
19
|
+
end
|
20
|
+
|
21
|
+
class SignResult
|
22
|
+
private_class_method :new
|
23
|
+
|
24
|
+
attr_reader :invalid_signers, :signatures
|
25
|
+
end
|
26
|
+
|
27
|
+
class EncryptResult
|
28
|
+
private_class_method :new
|
29
|
+
|
30
|
+
attr_reader :invalid_recipients
|
31
|
+
end
|
32
|
+
|
33
|
+
class InvalidKey
|
34
|
+
private_class_method :new
|
35
|
+
|
36
|
+
attr_reader :fpr, :reason
|
37
|
+
alias fingerprint fpr
|
38
|
+
end
|
39
|
+
|
40
|
+
class NewSignature
|
41
|
+
private_class_method :new
|
42
|
+
|
43
|
+
attr_reader :type, :pubkey_algo, :hash_algo, :sig_class, :fpr
|
44
|
+
alias fingerprint fpr
|
45
|
+
|
46
|
+
def timestamp
|
47
|
+
Time.at(@timestamp)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ImportStatus
|
52
|
+
private_class_method :new
|
53
|
+
|
54
|
+
attr_reader :fpr, :result, :status
|
55
|
+
alias fingerprint fpr
|
56
|
+
end
|
57
|
+
|
58
|
+
class ImportResult
|
59
|
+
private_class_method :new
|
60
|
+
|
61
|
+
attr_reader :considered, :no_user_id, :imported, :imported_rsa, :unchanged
|
62
|
+
attr_reader :new_user_ids, :new_sub_keys, :new_signatures, :new_revocations
|
63
|
+
attr_reader :secret_read, :secret_imported, :secret_unchanged
|
64
|
+
attr_reader :not_imported, :imports
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module GPGME
|
2
|
+
class Signature
|
3
|
+
private_class_method :new
|
4
|
+
|
5
|
+
attr_reader :summary, :fpr, :status, :notations, :wrong_key_usage
|
6
|
+
attr_reader :validity, :validity_reason
|
7
|
+
attr_reader :pka_trust, :pka_address
|
8
|
+
alias fingerprint fpr
|
9
|
+
|
10
|
+
##
|
11
|
+
# Returns true if the signature is correct
|
12
|
+
def valid?
|
13
|
+
status_code == GPGME::GPG_ERR_NO_ERROR
|
14
|
+
end
|
15
|
+
|
16
|
+
def expired_signature?
|
17
|
+
status_code == GPGME::GPG_ERR_SIG_EXPIRED
|
18
|
+
end
|
19
|
+
|
20
|
+
def expired_key?
|
21
|
+
status_code == GPGME::GPG_ERR_KEY_EXPIRED
|
22
|
+
end
|
23
|
+
|
24
|
+
def revoked_key?
|
25
|
+
status_code == GPGME::GPG_ERR_CERT_REVOKED
|
26
|
+
end
|
27
|
+
|
28
|
+
def bad?
|
29
|
+
status_code == GPGME::GPG_ERR_BAD_SIGNATURE
|
30
|
+
end
|
31
|
+
|
32
|
+
def no_key?
|
33
|
+
status_code == GPGME::GPG_ERR_NO_PUBKEY
|
34
|
+
end
|
35
|
+
|
36
|
+
def status_code
|
37
|
+
GPGME::gpgme_err_code(status)
|
38
|
+
end
|
39
|
+
|
40
|
+
def from
|
41
|
+
@from ||= begin
|
42
|
+
Ctx.new do |ctx|
|
43
|
+
if from_key = ctx.get_key(fingerprint)
|
44
|
+
"#{from_key.subkeys[0].keyid} #{from_key.uids[0].uid}"
|
45
|
+
else
|
46
|
+
fingerprint
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def key
|
53
|
+
@key ||= begin
|
54
|
+
Ctx.new do |ctx|
|
55
|
+
@key = ctx.get_key(fingerprint)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def timestamp
|
61
|
+
Time.at(@timestamp)
|
62
|
+
end
|
63
|
+
|
64
|
+
def exp_timestamp
|
65
|
+
Time.at(@exp_timestamp)
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
case status_code
|
70
|
+
when GPGME::GPG_ERR_NO_ERROR
|
71
|
+
"Good signature from #{from}"
|
72
|
+
when GPGME::GPG_ERR_SIG_EXPIRED
|
73
|
+
"Expired signature from #{from}"
|
74
|
+
when GPGME::GPG_ERR_KEY_EXPIRED
|
75
|
+
"Signature made from expired key #{from}"
|
76
|
+
when GPGME::GPG_ERR_CERT_REVOKED
|
77
|
+
"Signature made from revoked key #{from}"
|
78
|
+
when GPGME::GPG_ERR_BAD_SIGNATURE
|
79
|
+
"Bad signature from #{from}"
|
80
|
+
when GPGME::GPG_ERR_NO_PUBKEY
|
81
|
+
"No public key for #{from}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module GPGME
|
2
|
+
class SubKey
|
3
|
+
private_class_method :new
|
4
|
+
|
5
|
+
attr_reader :pubkey_algo, :length, :keyid, :fpr
|
6
|
+
alias fingerprint fpr
|
7
|
+
|
8
|
+
include KeyCommon
|
9
|
+
|
10
|
+
def timestamp
|
11
|
+
Time.at(@timestamp)
|
12
|
+
end
|
13
|
+
|
14
|
+
def expires
|
15
|
+
Time.at(@expires)
|
16
|
+
end
|
17
|
+
|
18
|
+
def expired
|
19
|
+
return false if @expires == 0
|
20
|
+
@expires < Time.now.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def sha
|
24
|
+
(@fingerprint || @keyid)[-8 .. -1]
|
25
|
+
end
|
26
|
+
|
27
|
+
PUBKEY_ALGO_LETTERS = {
|
28
|
+
PK_RSA => "R",
|
29
|
+
PK_ELG_E => "g",
|
30
|
+
PK_ELG => "G",
|
31
|
+
PK_DSA => "D"
|
32
|
+
}
|
33
|
+
|
34
|
+
def pubkey_algo_letter
|
35
|
+
PUBKEY_ALGO_LETTERS[@pubkey_algo] || "?"
|
36
|
+
end
|
37
|
+
|
38
|
+
def inspect
|
39
|
+
sprintf("#<#{self.class} %s %4d%s/%s %s trust=%s, capability=%s>",
|
40
|
+
secret? ? 'ssc' : 'sub',
|
41
|
+
length,
|
42
|
+
pubkey_algo_letter,
|
43
|
+
(@fingerprint || @keyid)[-8 .. -1],
|
44
|
+
timestamp.strftime('%Y-%m-%d'),
|
45
|
+
trust.inspect,
|
46
|
+
capability.inspect)
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
sprintf("%s %4d%s/%s %s\n",
|
51
|
+
secret? ? 'ssc' : 'sub',
|
52
|
+
length,
|
53
|
+
pubkey_algo_letter,
|
54
|
+
(@fingerprint || @keyid)[-8 .. -1],
|
55
|
+
timestamp.strftime('%Y-%m-%d'))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GPGME
|
2
|
+
class UserID
|
3
|
+
private_class_method :new
|
4
|
+
|
5
|
+
attr_reader :validity, :uid, :name, :comment, :email, :signatures
|
6
|
+
|
7
|
+
def revoked?
|
8
|
+
@revoked == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def invalid?
|
12
|
+
@invalid == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
def inspect
|
16
|
+
"#<#{self.class} #{name} <#{email}> \
|
17
|
+
validity=#{VALIDITY_NAMES[validity]}, signatures=#{signatures.inspect}>"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/gpgme.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'gpgme/ffi'
|
2
|
+
|
3
|
+
# TODO without this call one can't GPGME::Ctx.new, find out why
|
4
|
+
GPGME::gpgme_check_version(nil)
|
5
|
+
|
6
|
+
require 'gpgme/constants'
|
7
|
+
require 'gpgme/ctx'
|
8
|
+
require 'gpgme/data'
|
9
|
+
require 'gpgme/error'
|
10
|
+
require 'gpgme/io_callbacks'
|
11
|
+
require 'gpgme/key_common'
|
12
|
+
require 'gpgme/key'
|
13
|
+
require 'gpgme/sub_key'
|
14
|
+
require 'gpgme/key_sig'
|
15
|
+
require 'gpgme/misc'
|
16
|
+
require 'gpgme/signature'
|
17
|
+
require 'gpgme/user_id'
|
18
|
+
require 'gpgme/engine'
|
19
|
+
require 'gpgme/crypto'
|
20
|
+
|
21
|
+
module GPGME
|
22
|
+
class << self
|
23
|
+
|
24
|
+
# From the c extension
|
25
|
+
alias pubkey_algo_name gpgme_pubkey_algo_name
|
26
|
+
alias hash_algo_name gpgme_hash_algo_name
|
27
|
+
|
28
|
+
##
|
29
|
+
# Auxiliary method used by all the library to generate exceptions
|
30
|
+
# from error codes returned by the C extension.
|
31
|
+
def error_to_exception(err)
|
32
|
+
case GPGME::gpgme_err_code(err)
|
33
|
+
when GPG_ERR_EOF
|
34
|
+
EOFError.new
|
35
|
+
when GPG_ERR_NO_ERROR
|
36
|
+
nil
|
37
|
+
when GPG_ERR_GENERAL
|
38
|
+
Error::General.new(err)
|
39
|
+
when GPG_ERR_ENOMEM
|
40
|
+
Errno::ENOMEM.new
|
41
|
+
when GPG_ERR_INV_VALUE
|
42
|
+
Error::InvalidValue.new(err)
|
43
|
+
when GPG_ERR_UNUSABLE_PUBKEY
|
44
|
+
Error::UnusablePublicKey.new(err)
|
45
|
+
when GPG_ERR_UNUSABLE_SECKEY
|
46
|
+
Error::UnusableSecretKey.new(err)
|
47
|
+
when GPG_ERR_NO_DATA
|
48
|
+
Error::NoData.new(err)
|
49
|
+
when GPG_ERR_CONFLICT
|
50
|
+
Error::Conflict.new(err)
|
51
|
+
when GPG_ERR_NOT_IMPLEMENTED
|
52
|
+
Error::NotImplemented.new(err)
|
53
|
+
when GPG_ERR_DECRYPT_FAILED
|
54
|
+
Error::DecryptFailed.new(err)
|
55
|
+
when GPG_ERR_BAD_PASSPHRASE
|
56
|
+
Error::BadPassphrase.new(err)
|
57
|
+
when GPG_ERR_CANCELED
|
58
|
+
Error::Canceled.new(err)
|
59
|
+
when GPG_ERR_INV_ENGINE
|
60
|
+
Error::InvalidEngine.new(err)
|
61
|
+
when GPG_ERR_AMBIGUOUS_NAME
|
62
|
+
Error::AmbiguousName.new(err)
|
63
|
+
when GPG_ERR_WRONG_KEY_USAGE
|
64
|
+
Error::WrongKeyUsage.new(err)
|
65
|
+
when GPG_ERR_CERT_REVOKED
|
66
|
+
Error::CertificateRevoked.new(err)
|
67
|
+
when GPG_ERR_CERT_EXPIRED
|
68
|
+
Error::CertificateExpired.new(err)
|
69
|
+
when GPG_ERR_NO_CRL_KNOWN
|
70
|
+
Error::NoCRLKnown.new(err)
|
71
|
+
when GPG_ERR_NO_POLICY_MATCH
|
72
|
+
Error::NoPolicyMatch.new(err)
|
73
|
+
when GPG_ERR_NO_SECKEY
|
74
|
+
Error::NoSecretKey.new(err)
|
75
|
+
when GPG_ERR_MISSING_CERT
|
76
|
+
Error::MissingCertificate.new(err)
|
77
|
+
when GPG_ERR_BAD_CERT_CHAIN
|
78
|
+
Error::BadCertificateChain.new(err)
|
79
|
+
when GPG_ERR_UNSUPPORTED_ALGORITHM
|
80
|
+
Error::UnsupportedAlgorithm.new(err)
|
81
|
+
when GPG_ERR_BAD_SIGNATURE
|
82
|
+
Error::BadSignature.new(err)
|
83
|
+
when GPG_ERR_NO_PUBKEY
|
84
|
+
Error::NoPublicKey.new(err)
|
85
|
+
else
|
86
|
+
Error.new(err)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# TODO find out what it does, can't seem to find a proper parameter that
|
92
|
+
# returns something other than nil.
|
93
|
+
def check_version(options = nil)
|
94
|
+
version = nil
|
95
|
+
if options.kind_of?(String)
|
96
|
+
version = options
|
97
|
+
elsif options.include?(:version)
|
98
|
+
version = options[:version]
|
99
|
+
end
|
100
|
+
unless GPGME::gpgme_check_version(version)
|
101
|
+
raise Error::InvalidVersion.new
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|