gpgme-ffi 3.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.
- 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
|