benburkert-gpgme 0.1.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/.gitignore +6 -0
- data/COPYING +340 -0
- data/COPYING.LESSER +510 -0
- data/Gemfile +6 -0
- data/History.txt +15 -0
- data/Manifest.txt +18 -0
- data/README.rdoc +162 -0
- data/Rakefile +37 -0
- data/THANKS +15 -0
- data/benburkert-gpgme.gemspec +30 -0
- data/examples/edit.rb +77 -0
- data/examples/genkey.rb +55 -0
- data/examples/keylist.rb +6 -0
- data/examples/roundtrip.rb +39 -0
- data/examples/sign.rb +29 -0
- data/examples/verify.rb +6 -0
- data/ext/gpgme/extconf.rb +26 -0
- data/ext/gpgme/gpgme_n.c +2622 -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 +177 -0
- data/lib/gpgme/engine.rb +76 -0
- data/lib/gpgme/error.rb +66 -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 +108 -0
- data/test/crypto_test.rb +242 -0
- data/test/ctx_test.rb +426 -0
- data/test/data_test.rb +116 -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 +201 -0
- data/test/signature_test.rb +48 -0
- data/test/sub_key_test.rb +45 -0
- data/test/support/resources.rb +516 -0
- data/test/test_helper.rb +79 -0
- metadata +196 -0
data/lib/gpgme/error.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module GPGME
|
2
|
+
class Error < StandardError
|
3
|
+
def initialize(error)
|
4
|
+
@error = error
|
5
|
+
end
|
6
|
+
attr_reader :error
|
7
|
+
|
8
|
+
# Return the error code.
|
9
|
+
#
|
10
|
+
# The error code indicates the type of an error, or the reason why
|
11
|
+
# an operation failed.
|
12
|
+
def code
|
13
|
+
GPGME::gpgme_err_code(@error)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return the error source.
|
17
|
+
#
|
18
|
+
# The error source has not a precisely defined meaning. Sometimes
|
19
|
+
# it is the place where the error happened, sometimes it is the
|
20
|
+
# place where an error was encoded into an error value. Usually
|
21
|
+
# the error source will give an indication to where to look for
|
22
|
+
# the problem. This is not always true, but it is attempted to
|
23
|
+
# achieve this goal.
|
24
|
+
def source
|
25
|
+
GPGME::gpgme_err_source(@error)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return a description of the error code.
|
29
|
+
def message
|
30
|
+
GPGME::gpgme_strerror(@error)
|
31
|
+
end
|
32
|
+
|
33
|
+
class General < self; end
|
34
|
+
class InvalidValue < self; end
|
35
|
+
class UnusablePublicKey < self
|
36
|
+
attr_accessor :keys
|
37
|
+
end
|
38
|
+
class UnusableSecretKey < self
|
39
|
+
attr_accessor :keys
|
40
|
+
end
|
41
|
+
class NoData < self; end
|
42
|
+
class Conflict < self; end
|
43
|
+
class NotImplemented < self; end
|
44
|
+
class DecryptFailed < self; end
|
45
|
+
class BadPassphrase < self; end
|
46
|
+
class Canceled < self; end
|
47
|
+
class InvalidEngine < self; end
|
48
|
+
class AmbiguousName < self; end
|
49
|
+
class WrongKeyUsage < self
|
50
|
+
attr_accessor :key_usage
|
51
|
+
end
|
52
|
+
class CertificateRevoked < self; end
|
53
|
+
class CertificateExpired < self; end
|
54
|
+
class NoCRLKnown < self; end
|
55
|
+
class NoPolicyMatch < self; end
|
56
|
+
class NoSecretKey < self; end
|
57
|
+
class MissingCertificate < self; end
|
58
|
+
class BadCertificateChain < self; end
|
59
|
+
class UnsupportedAlgorithm < self
|
60
|
+
attr_accessor :algorithm
|
61
|
+
end
|
62
|
+
class BadSignature < self; end
|
63
|
+
class NoPublicKey < self; end
|
64
|
+
class InvalidVersion < self; end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module GPGME
|
2
|
+
class IOCallbacks
|
3
|
+
def initialize(io)
|
4
|
+
@io = io
|
5
|
+
end
|
6
|
+
|
7
|
+
def read(hook, length)
|
8
|
+
@io.read(length)
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(hook, buffer, length)
|
12
|
+
@io.write(buffer[0 .. length])
|
13
|
+
end
|
14
|
+
|
15
|
+
def seek(hook, offset, whence)
|
16
|
+
return @io.pos if offset == 0 && whence == IO::SEEK_CUR
|
17
|
+
@io.seek(offset, whence)
|
18
|
+
@io.pos
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
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@exampl.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
|
+
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
|