gpgme-2.0.16/ 0000755 0000041 0000041 00000000000 13234766066 012744 5 ustar www-data www-data gpgme-2.0.16/examples/ 0000755 0000041 0000041 00000000000 13234766063 014557 5 ustar www-data www-data gpgme-2.0.16/examples/verify.rb 0000755 0000041 0000041 00000000236 13234766063 016414 0 ustar www-data www-data #!/usr/bin/env ruby
require 'gpgme'
crypto = GPGME::Crypto.new
signature = GPGME::Data.new(ARGF.read)
crypto.verify(signature) do |sig|
puts(sig.to_s)
end
gpgme-2.0.16/examples/genkey.rb 0000755 0000041 0000041 00000002514 13234766063 016373 0 ustar www-data www-data #!/usr/bin/env ruby
require 'gpgme'
# If you do not have gpg-agent installed, comment out the following
# and set it as :passphrase_callback.
#
# def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
# $stderr.write("Passphrase for #{uid_hint}: ")
# $stderr.flush
# begin
# system('stty -echo')
# io = IO.for_fd(fd, 'w')
# io.puts(gets)
# io.flush
# ensure
# (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
# system('stty echo')
# end
# $stderr.puts
# end
unless ENV['GPG_AGENT_INFO']
$stderr.puts("gpg-agent is not running. See the comment in #{$0}.")
exit(1)
end
unless ENV['GNUPGHOME']
$stderr.write('As GNUPGHOME is not set, the generated key pair will be stored into *your* keyring. Really proceed? (y/N) ')
$stderr.flush
exit(1) unless gets.chomp == 'y'
end
def progfunc(hook, what, type, current, total)
$stderr.write("#{what}: #{current}/#{total}\r")
$stderr.flush
end
ctx = GPGME::Ctx.new({:progress_callback => method(:progfunc),
# :passphrase_callback => method(:passfunc)
})
ctx.genkey(<<'EOF', nil, nil)
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 1024
Name-Real: Joe Tester
Name-Comment: with stupid passphrase
Name-Email: joe@foo.bar
Expire-Date: 0
Passphrase: abc
EOF
$stderr.puts
gpgme-2.0.16/examples/edit.rb 0000755 0000041 0000041 00000003517 13234766063 016042 0 ustar www-data www-data #!/usr/bin/env ruby
require 'gpgme'
# If you do not have gpg-agent installed, comment out the following
# and set it as :passphrase_callback.
#
# def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
# $stderr.write("Passphrase for #{uid_hint}: ")
# $stderr.flush
# begin
# system('stty -echo')
# io = IO.for_fd(fd, 'w')
# io.puts(gets)
# io.flush
# ensure
# (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
# system('stty echo')
# end
# $stderr.puts
# end
unless ENV['GPG_AGENT_INFO']
$stderr.puts("gpg-agent is not running. See the comment in #{$0}.")
exit(1)
end
unless ENV['GNUPGHOME']
$stderr.write('As GNUPGHOME is not set, the generated key pair will be stored into *your* keyring. Really proceed? (y/N) ')
$stderr.flush
exit(1) unless gets.chomp == 'y'
end
unless ARGV.length == 1
$stderr.puts("Usage: #{$0} KEYGRIP")
exit(1)
end
def progfunc(hook, what, type, current, total)
$stderr.write("#{what}: #{current}/#{total}\r")
$stderr.flush
end
def editfunc(hook, status, args, fd)
case status
when GPGME::GPGME_STATUS_GET_BOOL
begin
$stderr.write("#{args} (y/n) ")
$stderr.flush
line = gets
end until line =~ /\A\s*[ny]\s*\z/
io = IO.for_fd(fd)
io.puts(line.strip)
io.flush
when GPGME::GPGME_STATUS_GET_LINE, GPGME::GPGME_STATUS_GET_HIDDEN
$stderr.write("#{args}: ")
$stderr.flush
line = gets
io = IO.for_fd(fd)
io.puts(line)
io.flush
else
$stderr.puts([status, args].inspect)
end
end
ctx = GPGME::Ctx.new({:progress_callback => method(:progfunc),
# :passphrase_callback => method(:passfunc)
})
keystr = ARGV.shift
keys = ctx.keys(keystr)
if keys.empty?
$stderr.puts("Can't find key for \"#{keystr}\"")
exit(1)
end
$stderr.puts(keys.first.inspect)
ctx.edit_key(keys.first, method(:editfunc))
gpgme-2.0.16/examples/roundtrip.rb 0000755 0000041 0000041 00000002060 13234766063 017133 0 ustar www-data www-data #!/usr/bin/env ruby
require 'gpgme'
# If you do not have gpg-agent installed, comment out the following
# and set it as :passphrase_callback.
#
# def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
# $stderr.write("Passphrase for #{uid_hint}: ")
# $stderr.flush
# begin
# system('stty -echo')
# io = IO.for_fd(fd, 'w')
# io.puts(gets)
# io.flush
# ensure
# (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
# system('stty echo')
# end
# $stderr.puts
# end
unless ENV['GPG_AGENT_INFO']
$stderr.puts("gpg-agent is not running. See the comment in #{$0}.")
exit(1)
end
plain = 'test test test'
puts("Plaintext:\n#{plain}")
# Perform symmetric encryption on PLAIN.
crypto = GPGME::Crypto.new(:armor => true)
cipher = crypto.encrypt(plain, {:symmetric => true,
# :passphrase_callback => method(:passfunc)
})
str = cipher.read
puts("Ciphertext:\n#{str}")
cipher = GPGME::Data.new(str)
plain = crypto.decrypt(cipher, {
# :passphrase_callback => method(:passfunc)
})
puts("Plaintext:\n#{plain.read}")
gpgme-2.0.16/examples/keylist.rb 0000755 0000041 0000041 00000000154 13234766063 016573 0 ustar www-data www-data #!/usr/bin/env ruby
require 'gpgme'
ctx = GPGME::Ctx.new
ctx.each_key(ARGV.shift) do |key|
puts(key)
end
gpgme-2.0.16/examples/sign.rb 0000755 0000041 0000041 00000001471 13234766063 016052 0 ustar www-data www-data #!/usr/bin/env ruby
require 'gpgme'
# If you do not have gpg-agent installed, comment out the following
# and set it as :passphrase_callback.
#
# def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
# $stderr.write("Passphrase for #{uid_hint}: ")
# $stderr.flush
# begin
# system('stty -echo')
# io = IO.for_fd(fd, 'w')
# io.puts(gets)
# io.flush
# ensure
# (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
# system('stty echo')
# end
# $stderr.puts
# end
unless ENV['GPG_AGENT_INFO']
$stderr.puts("gpg-agent is not running. See the comment in #{$0}.")
exit(1)
end
crypto = GPGME::Crypto.new
signature = crypto.clearsign('test test test', {
# :passphrase_callback => method(:passfunc)
})
puts signature.read
gpgme-2.0.16/lib/ 0000755 0000041 0000041 00000000000 13234766063 013507 5 ustar www-data www-data gpgme-2.0.16/lib/gpgme.rb 0000644 0000041 0000041 00000006066 13234766063 015143 0 ustar www-data www-data $:.push File.expand_path("../..", __FILE__) # C extension is in the root
require 'gpgme_n'
# TODO without this call one can't GPGME::Ctx.new, find out why
GPGME::gpgme_check_version(nil)
require 'gpgme/constants'
require 'gpgme/ctx'
require 'gpgme/data'
require 'gpgme/error'
require 'gpgme/io_callbacks'
require 'gpgme/key_common'
require 'gpgme/key'
require 'gpgme/sub_key'
require 'gpgme/key_sig'
require 'gpgme/misc'
require 'gpgme/signature'
require 'gpgme/user_id'
require 'gpgme/engine'
require 'gpgme/crypto'
module GPGME
class << self
# From the c extension
alias pubkey_algo_name gpgme_pubkey_algo_name
alias hash_algo_name gpgme_hash_algo_name
##
# Auxiliary method used by all the library to generate exceptions
# from error codes returned by the C extension.
def error_to_exception(err)
case GPGME::gpgme_err_code(err)
when GPG_ERR_EOF
EOFError.new
when GPG_ERR_NO_ERROR
nil
when GPG_ERR_GENERAL
Error::General.new(err)
when GPG_ERR_ENOMEM
Errno::ENOMEM.new
when GPG_ERR_INV_VALUE
Error::InvalidValue.new(err)
when GPG_ERR_UNUSABLE_PUBKEY
Error::UnusablePublicKey.new(err)
when GPG_ERR_UNUSABLE_SECKEY
Error::UnusableSecretKey.new(err)
when GPG_ERR_NO_DATA
Error::NoData.new(err)
when GPG_ERR_CONFLICT
Error::Conflict.new(err)
when GPG_ERR_NOT_IMPLEMENTED
Error::NotImplemented.new(err)
when GPG_ERR_DECRYPT_FAILED
Error::DecryptFailed.new(err)
when GPG_ERR_BAD_PASSPHRASE
Error::BadPassphrase.new(err)
when GPG_ERR_CANCELED
Error::Canceled.new(err)
when GPG_ERR_INV_ENGINE
Error::InvalidEngine.new(err)
when GPG_ERR_AMBIGUOUS_NAME
Error::AmbiguousName.new(err)
when GPG_ERR_WRONG_KEY_USAGE
Error::WrongKeyUsage.new(err)
when GPG_ERR_CERT_REVOKED
Error::CertificateRevoked.new(err)
when GPG_ERR_CERT_EXPIRED
Error::CertificateExpired.new(err)
when GPG_ERR_NO_CRL_KNOWN
Error::NoCRLKnown.new(err)
when GPG_ERR_NO_POLICY_MATCH
Error::NoPolicyMatch.new(err)
when GPG_ERR_NO_SECKEY
Error::NoSecretKey.new(err)
when GPG_ERR_MISSING_CERT
Error::MissingCertificate.new(err)
when GPG_ERR_BAD_CERT_CHAIN
Error::BadCertificateChain.new(err)
when GPG_ERR_UNSUPPORTED_ALGORITHM
Error::UnsupportedAlgorithm.new(err)
when GPG_ERR_BAD_SIGNATURE
Error::BadSignature.new(err)
when GPG_ERR_NO_PUBKEY
Error::NoPublicKey.new(err)
else
Error.new(err)
end
end
##
# TODO find out what it does, can't seem to find a proper parameter that
# returns something other than nil.
def check_version(options = nil)
version = nil
if options.kind_of?(String)
version = options
elsif options.include?(:version)
version = options[:version]
end
unless GPGME::gpgme_check_version(version)
raise Error::InvalidVersion.new
end
end
end
end
gpgme-2.0.16/lib/gpgme/ 0000755 0000041 0000041 00000000000 13234766063 014606 5 ustar www-data www-data gpgme-2.0.16/lib/gpgme/user_id.rb 0000644 0000041 0000041 00000000565 13234766063 016573 0 ustar www-data www-data module GPGME
class UserID
private_class_method :new
attr_reader :validity, :uid, :name, :comment, :email, :signatures
def revoked?
@revoked == 1
end
def invalid?
@invalid == 1
end
def inspect
"#<#{self.class} #{name} <#{email}> \
validity=#{VALIDITY_NAMES[validity]}, signatures=#{signatures.inspect}>"
end
end
end
gpgme-2.0.16/lib/gpgme/ctx.rb 0000644 0000041 0000041 00000037661 13234766063 015746 0 ustar www-data www-data module GPGME
##
# A context within which all cryptographic operations are performed.
#
# More operations can be done which are not available in the higher level
# API. Note how to create a new instance of this class in {GPGME::Ctx.new}.
#
class Ctx
##
# Create a new instance from the given +options+. Must be released either
# executing the operations inside a block, or executing {GPGME::Ctx#release}
# afterwards.
#
# @param [Hash] options
# The optional parameters are as follows:
# * +:protocol+ Either +PROTOCOL_OpenPGP+ or +PROTOCOL_CMS+.
# * +:armor+ will return ASCII armored outputs if specified true.
# * +:textmode+ if +true+, inform the recipient that the input is text.
# * +:keylist_mode+ One of: +KEYLIST_MODE_LOCAL+, +KEYLIST_MODE_EXTERN+,
# +KEYLIST_MODE_SIGS+ or +KEYLIST_MODE_VALIDATE+.
# * +:pinentry_mode+ One of: +PINENTRY_MODE_DEFAULT+,
# +PINENTRY_MODE_ASK+, +PINENTRY_MODE_CANCEL+,
# +PINENTRY_MODE_ERROR+, or +PINENTRY_MODE_LOOPBACK+.
# * +:offline+ if set to true, dirmngr will not contact external services
# * +:password+ password of the passphrased password being used.
# * +:passphrase_callback+ A callback function. See {#set_passphrase_callback}.
# * +:passphrase_callback_value+ An object passed to passphrase_callback.
# * +:progress_callback+ A callback function. See {#set_progress_callback}.
# * +:progress_callback_value+ An object passed to progress_callback.
# * +:status_callback+ A callback function. See {#set_status_callback}.
# * +:status_callback_value+ An object passed to status_callback.
#
# @example
# ctx = GPGME::Ctx.new
# # operate on ctx
# ctx.release
#
# @example
# GPGME::Ctx.new do |ctx|
# # operate on ctx
# end
#
def self.new(options = {})
rctx = []
err = GPGME::gpgme_new(rctx)
exc = GPGME::error_to_exception(err)
raise exc if exc
ctx = rctx[0]
ctx.protocol = options[:protocol] if options[:protocol]
ctx.armor = options[:armor] if options[:armor]
ctx.textmode = options[:textmode] if options[:textmode]
ctx.keylist_mode = options[:keylist_mode] if options[:keylist_mode]
ctx.pinentry_mode = options[:pinentry_mode] if options[:pinentry_mode]
ctx.offline = options[:offline] if options[:offline]
if options[:password]
ctx.set_passphrase_callback GPGME::Ctx.method(:pass_function),
options[:password]
else
if options[:passphrase_callback]
ctx.set_passphrase_callback options[:passphrase_callback],
options[:passphrase_callback_value]
end
end
if options[:progress_callback]
ctx.set_progress_callback options[:progress_callback],
options[:progress_callback_value]
end
if options[:status_callback]
ctx.set_status_callback options[:status_callback],
options[:status_callback_value]
end
if block_given?
begin
yield ctx
ensure
GPGME::gpgme_release(ctx)
end
else
ctx
end
end
##
# Releases the Ctx instance. Must be called if it was initialized without
# a block.
#
# @example
# ctx = GPGME::Ctx.new
# # operate on ctx
# ctx.release
#
def release
GPGME::gpgme_release(self)
end
##
# Getters and setters
##
# Set the +protocol+ used within this context. See {GPGME::Ctx.new} for
# possible values.
def protocol=(proto)
err = GPGME::gpgme_set_protocol(self, proto)
exc = GPGME::error_to_exception(err)
raise exc if exc
proto
end
# Return the +protocol+ used within this context.
def protocol
GPGME::gpgme_get_protocol(self)
end
# Tell whether the output should be ASCII armored.
def armor=(yes)
GPGME::gpgme_set_armor(self, yes ? 1 : 0)
yes
end
# Return true if the output is ASCII armored.
def armor
GPGME::gpgme_get_armor(self) == 1 ? true : false
end
# Tell whether canonical text mode should be used.
def textmode=(yes)
GPGME::gpgme_set_textmode(self, yes ? 1 : 0)
yes
end
# Return true if canonical text mode is enabled.
def textmode
GPGME::gpgme_get_textmode(self) == 1 ? true : false
end
# Change the default behaviour of the key listing functions.
def keylist_mode=(mode)
GPGME::gpgme_set_keylist_mode(self, mode)
mode
end
# Return the current key listing mode.
def keylist_mode
GPGME::gpgme_get_keylist_mode(self)
end
# Change the default behaviour of the pinentry invocation.
def pinentry_mode=(mode)
GPGME::gpgme_set_pinentry_mode(self, mode)
mode
end
# Return the current pinentry mode.
def pinentry_mode
GPGME::gpgme_get_pinentry_mode(self)
end
# Change the default behaviour of the dirmngr that might require
# connections to external services.
def offline=(mode)
GPGME::gpgme_set_offline(self, mode)
mode
end
# Return the current offline mode.
def offline
GPGME::gpgme_get_offline(self)
end
##
# Passphrase and progress callbacks
##
# Set the passphrase callback with given hook value.
# +passfunc+ should respond to +call+ with 5 arguments.
#
# * +obj+ the parameter +:passphrase_callback_value+ passed when creating
# the {GPGME::Ctx} object.
# * +uid_hint+ hint as to what key are we asking the password for. Ex:
#
# +CFB3294A50C2CFD7 Albert Llop +
#
# * +passphrase_info+
# * +prev_was_bad+ 0 if it's the first time the password is being asked,
# 1 otherwise.
# * +fd+ file descriptor where the password must be written too.
#
# Expects a Method object which can be obtained by the +method+ method
# (really..).
#
# ctx.set_passphrase_callback(MyModule.method(:passfunc))
#
# @example this method will simply return +maria+ as password.
# def pass_function(obj, uid_hint, passphrase_info, prev_was_bad, fd)
# io = IO.for_fd(fd, 'w')
# io.puts "maria"
# io.flush
# end
#
# @example this will interactively ask for the password
# def passfunc(obj, uid_hint, passphrase_info, prev_was_bad, fd)
# $stderr.write("Passphrase for #{uid_hint}: ")
# $stderr.flush
# begin
# system('stty -echo')
# io = IO.for_fd(fd, 'w')
# io.puts(gets)
# io.flush
# ensure
# (0 ... $_.length).each do |i| $_[i] = ?0 end if $_
# system('stty echo')
# end
# $stderr.puts
# end
#
# Note that this function doesn't work with GnuPG 2.0. You can
# use either GnuPG 1.x, which can be installed in parallel with
# GnuPG 2.0, or GnuPG 2.1, which has loopback pinentry feature (see
# {#pinentry_mode}).
def set_passphrase_callback(passfunc, hook_value = nil)
GPGME::gpgme_set_passphrase_cb(self, passfunc, hook_value)
end
alias set_passphrase_cb set_passphrase_callback
# Set the progress callback with given hook value.
# progfunc should respond to call
with 5 arguments.
#
# def progfunc(hook, what, type, current, total)
# $stderr.write("#{what}: #{current}/#{total}\r")
# $stderr.flush
# end
#
# ctx.set_progress_callback(method(:progfunc))
#
def set_progress_callback(progfunc, hook_value = nil)
GPGME::gpgme_set_progress_cb(self, progfunc, hook_value)
end
alias set_progress_cb set_progress_callback
# Set the status callback with given hook value.
# +statusfunc+ should respond to +call+ with 3 arguments.
#
# * +obj+ the parameter +:status_callback_value+ passed when creating
# the {GPGME::Ctx} object.
# * +keyword+ the name of the status message
# * +args+ any arguments for the status message
#
# def status_function(obj, keyword, args)
# $stderr.puts("#{keyword} #{args}")
# return 0
# end
def set_status_callback(statusfunc, hook_value = nil)
GPGME::gpgme_set_status_cb(self, statusfunc, hook_value)
end
alias set_status_cb set_status_callback
##
# Searching and iterating through keys. Used by {GPGME::Key.find}
##
# Initiate a key listing operation for given pattern. If +pattern+ is
# +nil+, all available keys are returned. If +secret_only<+ is +true+,
# only secret keys are returned.
#
# Used by {GPGME::Ctx#each_key}
def keylist_start(pattern = nil, secret_only = false)
err = GPGME::gpgme_op_keylist_start(self, pattern, secret_only ? 1 : 0)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
# Advance to the next key in the key listing operation.
#
# Used by {GPGME::Ctx#each_key}
def keylist_next
rkey = []
err = GPGME::gpgme_op_keylist_next(self, rkey)
exc = GPGME::error_to_exception(err)
raise exc if exc
rkey[0]
end
# End a pending key list operation.
#
# Used by {GPGME::Ctx#each_key}
def keylist_end
err = GPGME::gpgme_op_keylist_end(self)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
# Convenient method to iterate over keys.
#
# If +pattern+ is +nil+, all available keys are returned. If +secret_only+
# is +true+, only secret keys are returned.
#
# See {GPGME::Key.find} for an example of how to use, or for an easier way
# to use.
def each_key(pattern = nil, secret_only = false, &block)
keylist_start(pattern, secret_only)
begin
loop { yield keylist_next }
rescue EOFError
# The last key in the list has already been returned.
ensure
keylist_end
end
end
alias each_keys each_key
# Returns the keys that match the +pattern+, or all if +pattern+ is nil.
# Returns only secret keys if +secret_only+ is true.
def keys(pattern = nil, secret_only = nil)
keys = []
each_key(pattern, secret_only) do |key|
keys << key
end
keys
end
# Get the key with the +fingerprint+.
# If +secret+ is +true+, secret key is returned.
def get_key(fingerprint, secret = false)
rkey = []
err = GPGME::gpgme_get_key(self, fingerprint, rkey, secret ? 1 : 0)
exc = GPGME::error_to_exception(err)
raise exc if exc
rkey[0]
end
##
# Import/export and generation/deletion of keys
##
# Generate a new key pair.
# +parms+ is a string which looks like
#
#
# Key-Type: DSA
# Key-Length: 1024
# Subkey-Type: ELG-E
# Subkey-Length: 1024
# Name-Real: Joe Tester
# Name-Comment: with stupid passphrase
# Name-Email: joe@foo.bar
# Expire-Date: 0
# Passphrase: abc
#
#
# If +pubkey+ and +seckey+ are both set to +nil+, it stores the generated
# key pair into your key ring.
def generate_key(parms, pubkey = nil, seckey = nil)
err = GPGME::gpgme_op_genkey(self, parms, pubkey, seckey)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
alias genkey generate_key
# Extract the public keys that match the +recipients+. Returns a
# {GPGME::Data} object which is not rewinded (should do +seek(0)+
# before reading).
#
# Private keys cannot be exported due to GPGME restrictions.
#
# If passed, the key will be exported to +keydata+, which must be
# a {GPGME::Data} object.
def export_keys(recipients, keydata = Data.new)
err = GPGME::gpgme_op_export(self, recipients, 0, keydata)
exc = GPGME::error_to_exception(err)
raise exc if exc
keydata
end
alias export export_keys
# Add the keys in the data buffer to the key ring.
def import_keys(keydata)
err = GPGME::gpgme_op_import(self, keydata)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
alias import import_keys
def import_result
GPGME::gpgme_op_import_result(self)
end
# Delete the key from the key ring.
# If allow_secret is false, only public keys are deleted,
# otherwise secret keys are deleted as well.
def delete_key(key, allow_secret = false)
err = GPGME::gpgme_op_delete(self, key, allow_secret ? 1 : 0)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
alias delete delete_key
# Edit attributes of the key in the local key ring.
def edit_key(key, editfunc, hook_value = nil, out = Data.new)
err = GPGME::gpgme_op_edit(self, key, editfunc, hook_value, out)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
alias edit edit_key
# Edit attributes of the key on the card.
def edit_card_key(key, editfunc, hook_value = nil, out = Data.new)
err = GPGME::gpgme_op_card_edit(self, key, editfunc, hook_value, out)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
alias edit_card edit_card_key
alias card_edit edit_card_key
##
# Crypto operations
##
# Decrypt the ciphertext and return the plaintext.
def decrypt(cipher, plain = Data.new)
err = GPGME::gpgme_op_decrypt(self, cipher, plain)
exc = GPGME::error_to_exception(err)
raise exc if exc
plain
end
def decrypt_verify(cipher, plain = Data.new)
err = GPGME::gpgme_op_decrypt_verify(self, cipher, plain)
exc = GPGME::error_to_exception(err)
raise exc if exc
plain
end
def decrypt_result
GPGME::gpgme_op_decrypt_result(self)
end
# Verify that the signature in the data object is a valid signature.
def verify(sig, signed_text = nil, plain = Data.new)
err = GPGME::gpgme_op_verify(self, sig, signed_text, plain)
exc = GPGME::error_to_exception(err)
raise exc if exc
plain
end
def verify_result
GPGME::gpgme_op_verify_result(self)
end
# Remove the list of signers from this object.
def clear_signers
GPGME::gpgme_signers_clear(self)
end
# Add _keys_ to the list of signers.
def add_signer(*keys)
keys.each do |key|
err = GPGME::gpgme_signers_add(self, key)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
end
# Create a signature for the text.
# +plain+ is a data object which contains the text.
# +sig+ is a data object where the generated signature is stored.
def sign(plain, sig = Data.new, mode = GPGME::SIG_MODE_NORMAL)
err = GPGME::gpgme_op_sign(self, plain, sig, mode)
exc = GPGME::error_to_exception(err)
raise exc if exc
sig
end
def sign_result
GPGME::gpgme_op_sign_result(self)
end
# Encrypt the plaintext in the data object for the recipients and
# return the ciphertext.
def encrypt(recp, plain, cipher = Data.new, flags = 0)
err = GPGME::gpgme_op_encrypt(self, recp, flags, plain, cipher)
exc = GPGME::error_to_exception(err)
raise exc if exc
cipher
end
def encrypt_result
GPGME::gpgme_op_encrypt_result(self)
end
def encrypt_sign(recp, plain, cipher = Data.new, flags = 0)
err = GPGME::gpgme_op_encrypt_sign(self, recp, flags, plain, cipher)
exc = GPGME::error_to_exception(err)
raise exc if exc
cipher
end
def spawn(file, argv, datain, dataout, dataerr, flags = 0)
err = GPGME::gpgme_op_spawn(self, file, argv, datain, dataout, dataerr,
flags)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
def inspect
"#<#{self.class} protocol=#{PROTOCOL_NAMES[protocol] || protocol}, \
armor=#{armor}, textmode=#{textmode}, \
keylist_mode=#{KEYLIST_MODE_NAMES[keylist_mode]}>"
end
private
def self.pass_function(pass, uid_hint, passphrase_info, prev_was_bad, fd)
io = IO.for_fd(fd, 'w')
io.puts pass
io.flush
end
end
end
gpgme-2.0.16/lib/gpgme/signature.rb 0000644 0000041 0000041 00000003507 13234766063 017141 0 ustar www-data www-data module GPGME
class Signature
private_class_method :new
attr_reader :summary, :fpr, :status, :notations, :wrong_key_usage
attr_reader :validity, :validity_reason
attr_reader :pka_trust, :pka_address
alias fingerprint fpr
##
# Returns true if the signature is correct
def valid?
status_code == GPGME::GPG_ERR_NO_ERROR
end
def expired_signature?
status_code == GPGME::GPG_ERR_SIG_EXPIRED
end
def expired_key?
status_code == GPGME::GPG_ERR_KEY_EXPIRED
end
def revoked_key?
status_code == GPGME::GPG_ERR_CERT_REVOKED
end
def bad?
status_code == GPGME::GPG_ERR_BAD_SIGNATURE
end
def no_key?
status_code == GPGME::GPG_ERR_NO_PUBKEY
end
def status_code
GPGME::gpgme_err_code(status)
end
def from
@from ||= begin
Ctx.new do |ctx|
if from_key = ctx.get_key(fingerprint)
"#{from_key.subkeys[0].keyid} #{from_key.uids[0].uid}"
else
fingerprint
end
end
end
end
def key
@key ||= begin
Ctx.new do |ctx|
@key = ctx.get_key(fingerprint)
end
end
end
def timestamp
Time.at(@timestamp)
end
def exp_timestamp
Time.at(@exp_timestamp)
end
def to_s
case status_code
when GPGME::GPG_ERR_NO_ERROR
"Good signature from #{from}"
when GPGME::GPG_ERR_SIG_EXPIRED
"Expired signature from #{from}"
when GPGME::GPG_ERR_KEY_EXPIRED
"Signature made from expired key #{from}"
when GPGME::GPG_ERR_CERT_REVOKED
"Signature made from revoked key #{from}"
when GPGME::GPG_ERR_BAD_SIGNATURE
"Bad signature from #{from}"
when GPGME::GPG_ERR_NO_PUBKEY
"No public key for #{from}"
end
end
end
end
gpgme-2.0.16/lib/gpgme/compat.rb 0000644 0000041 0000041 00000002277 13234766063 016426 0 ustar www-data www-data require 'gpgme'
# TODO: Find why is this needed. I guess the name compat means it's just
# backwards compatibility. Consider removing?
module GPGME
GpgmeError = Error
GpgmeData = Data
GpgmeEngineInfo = EngineInfo
GpgmeCtx = Ctx
GpgmeKey = Key
GpgmeSubKey = SubKey
GpgmeUserID = UserID
GpgmeKeySig = KeySig
GpgmeVerifyResult = VerifyResult
GpgmeSignature = Signature
GpgmeDecryptResult = DecryptResult
GpgmeSignResult = SignResult
GpgmeEncryptResult = EncryptResult
GpgmeInvalidKey = InvalidKey
GpgmeNewSignature = NewSignature
GpgmeImportStatus = ImportStatus
GpgmeImportResult = ImportResult
class Ctx
# Set the data pointer to the beginning.
def rewind
seek(0)
end
end
def gpgme_data_rewind(dh)
begin
GPGME::gpgme_data_seek(dh, 0, IO::SEEK_SET)
rescue SystemCallError => e
return e.errno
end
end
module_function :gpgme_data_rewind
def gpgme_op_import_ext(ctx, keydata, nr)
err = GPGME::gpgme_op_import(ctx, keydata)
if GPGME::gpgme_err_code(err) == GPGME::GPG_ERR_NO_ERROR
result = GPGME::gpgme_op_import_result(ctx)
nr.push(result.considered)
end
end
module_function :gpgme_op_import_ext
end
gpgme-2.0.16/lib/gpgme/key_sig.rb 0000644 0000041 0000041 00000000764 13234766063 016574 0 ustar www-data www-data module GPGME
class KeySig
private_class_method :new
attr_reader :pubkey_algo, :keyid
def revoked?
@revoked == 1
end
def expired?
@expired == 1
end
def invalid?
@invalid == 1
end
def exportable?
@exportable == 1
end
def timestamp
Time.at(@timestamp)
end
def expires
Time.at(@expires)
end
def inspect
"#<#{self.class} #{keyid} timestamp=#{timestamp}, expires=#{expires}>"
end
end
end
gpgme-2.0.16/lib/gpgme/engine.rb 0000644 0000041 0000041 00000004560 13234766063 016405 0 ustar www-data www-data module GPGME
##
# Convenience methods to check different aspects of the gpg system
# installation.
module Engine
class << self
##
# Verify that the engine implementing the protocol +proto+ is installed in
# the system. Can be one of +PROTOCOL_OpenPGP+ or +PROTOCOL_CMS+.
#
# @return [Boolean] true if the engine is installed.
#
# @example
# GPGME::Engine.check_version(GPGME::PROTOCOL_OpenPGP) # => true
#
def check_version(proto)
err = GPGME::gpgme_engine_check_version(proto)
exc = GPGME::error_to_exception(err)
!exc
end
##
# Return an array of {GPGME::EngineInfo} structures of enabled engines.
#
# @example
# GPGME::Engine.info.first
# # => #
#
def info
rinfo = []
GPGME::gpgme_get_engine_info(rinfo)
rinfo
end
##
# Change the default configuration of the crypto engine implementing
# protocol +proto+.
#
# @param proto
# Can be one of +PROTOCOL_OpenPGP+ or +PROTOCOL_CMS+.
#
# @param file_name
# The file name of the executable program implementing the protocol.
#
# @param home_dir
# The directory name of the configuration directory.
#
# @example
# GPGME::Engine.set
#
def set_info(proto, file_name, home_dir)
err = GPGME::gpgme_set_engine_info(proto, file_name, home_dir)
exc = GPGME::error_to_exception(err)
raise exc if exc
end
##
# Sets the home dir for the configuration options. This way one could,
# for example, load the keys from a customized keychain.
#
# @example
# GPGME::Engine.home_dir = '/tmp'
#
def home_dir=(home_dir)
current = info.first
set_info current.protocol, current.file_name, home_dir
end
##
# Return the default configuration.
#
# @example
# GPGME::Engine.dirinfo('homedir')
# # => '/home/user/.gnupg"
#
def dirinfo(what)
GPGME::gpgme_get_dirinfo(what)
end
end # class << self
end # class Engine
end # module GPGME
gpgme-2.0.16/lib/gpgme/crypto.rb 0000644 0000041 0000041 00000030040 13234766063 016450 0 ustar www-data www-data module GPGME
##
# Different, independent methods providing the simplest possible API to
# execute crypto operations via GPG. All methods accept as options the same
# common options as {GPGME::Ctx.new}. Read the documentation for that class to
# know how to customize things further (like output stuff in ASCII armored
# format, for example).
#
# @example
# crypto = GPGME::Crypto.new :armor => true
# encrypted = crypto.encrypt 'Plain text'
#
class Crypto
attr_reader :default_options
def initialize(options = {})
@default_options = options
end
##
# Encrypts an element
#
# crypto.encrypt something, options
#
# Will return a {GPGME::Data} element which can then be read.
#
# Must have some key imported, look for {GPGME::Key.import} to know how
# to import one, or the gpg documentation to know how to create one
#
# @param plain
# Must be something that can be converted into a {GPGME::Data} object, or
# a {GPGME::Data} object itself.
#
# @param [Hash] options
# The optional parameters are as follows:
# * +:recipients+ for which recipient do you want to encrypt this file. It
# will pick the first one available if none specified. Can be an array of
# identifiers or just one (a string).
# * +:symmetric+ if set to true, will ignore +:recipients+, and will perform
# a symmetric encryption. Must provide a password via the +:password+
# option.
# * +:always_trust+ if set to true specifies all the recipients to be
# trusted, thus not requiring confirmation.
# * +:sign+ if set to true, performs a combined sign and encrypt operation.
# * +:signers+ if +:sign+ specified to true, a list of additional possible
# signers. Must be an array of sign identifiers.
# * +:output+ if specified, it will write the output into it. It will be
# converted to a {GPGME::Data} object, so it could be a file for example.
# * Any other option accepted by {GPGME::Ctx.new}
#
# @return [GPGME::Data] a {GPGME::Data} object that can be read.
#
# @example returns a {GPGME::Data} that can be later encrypted
# encrypted = crypto.encrypt "Hello world!"
# encrypted.read # => Encrypted stuff
#
# @example to be decrypted by someone@example.com.
# crypto.encrypt "Hello", :recipients => "someone@example.com"
#
# @example If I didn't trust any of my keys by default
# crypto.encrypt "Hello" # => GPGME::Error::General
# crypto.encrypt "Hello", :always_trust => true # => Will work fine
#
# @example encrypted string that can be decrypted and/or *verified*
# crypto.encrypt "Hello", :sign => true
#
# @example multiple signers
# crypto.encrypt "Hello", :sign => true, :signers => "extra@example.com"
#
# @example writing to a file instead
# file = File.open("signed.sec","w+")
# crypto.encrypt "Hello", :output => file # output written to signed.sec
#
# @raise [GPGME::Error::General] when trying to encrypt with a key that is
# not trusted, and +:always_trust+ wasn't specified
#
def encrypt(plain, options = {})
options = @default_options.merge options
plain_data = Data.new(plain)
cipher_data = Data.new(options[:output])
keys = Key.find(:public, options[:recipients])
keys = nil if options[:symmetric]
flags = 0
flags |= GPGME::ENCRYPT_ALWAYS_TRUST if options[:always_trust]
GPGME::Ctx.new(options) do |ctx|
begin
if options[:sign]
if options[:signers]
signers = Key.find(:public, options[:signers], :sign)
ctx.add_signer(*signers)
end
ctx.encrypt_sign(keys, plain_data, cipher_data, flags)
else
ctx.encrypt(keys, plain_data, cipher_data, flags)
end
rescue GPGME::Error::UnusablePublicKey => exc
exc.keys = ctx.encrypt_result.invalid_recipients
raise exc
rescue GPGME::Error::UnusableSecretKey => exc
exc.keys = ctx.sign_result.invalid_signers
raise exc
end
end
cipher_data.seek(0)
cipher_data
end
##
# Decrypts a previously encrypted element
#
# crypto.decrypt cipher, options, &block
#
# Must have the appropiate key to be able to decrypt, of course. Returns
# a {GPGME::Data} object which can then be read.
#
# @param cipher
# Must be something that can be converted into a {GPGME::Data} object,
# or a {GPGME::Data} object itself. It is the element that will be
# decrypted.
#
# @param [Hash] options
# The optional parameters:
# * +:output+ if specified, it will write the output into it. It will
# me converted to a {GPGME::Data} object, so it can also be a file,
# for example.
# * If the file was encrypted with symmentric encryption, must provide
# a :password option.
# * Any other option accepted by {GPGME::Ctx.new}
#
# @param &block
# In the block all the signatures are yielded, so one could verify them.
# See examples.
#
# @return [GPGME::Data] a {GPGME::Data} that can be read.
#
# @example Simple decrypt
# crypto.decrypt encrypted_data
#
# @example symmetric encryption, or passwored key
# crypto.decrypt encrypted_data, :password => "gpgme"
#
# @example Output to file
# file = File.open("decrypted.txt", "w+")
# crypto.decrypt encrypted_data, :output => file
#
# @example Verifying signatures
# crypto.decrypt encrypted_data do |signature|
# raise "Signature could not be verified" unless signature.valid?
# end
#
# @raise [GPGME::Error::UnsupportedAlgorithm] when the cipher was encrypted
# using an algorithm that's not supported currently.
#
# @raise [GPGME::Error::WrongKeyUsage] TODO Don't know when
#
# @raise [GPGME::Error::DecryptFailed] when the cipher was encrypted
# for a key that's not available currently.
def decrypt(cipher, options = {})
options = @default_options.merge options
plain_data = Data.new(options[:output])
cipher_data = Data.new(cipher)
GPGME::Ctx.new(options) do |ctx|
begin
ctx.decrypt_verify(cipher_data, plain_data)
rescue GPGME::Error::UnsupportedAlgorithm => exc
exc.algorithm = ctx.decrypt_result.unsupported_algorithm
raise exc
rescue GPGME::Error::WrongKeyUsage => exc
exc.key_usage = ctx.decrypt_result.wrong_key_usage
raise exc
end
verify_result = ctx.verify_result
if verify_result && block_given?
verify_result.signatures.each do |signature|
yield signature
end
end
end
plain_data.seek(0)
plain_data
end
##
# Creates a signature of a text
#
# crypto.sign text, options
#
# Must have the appropiate key to be able to decrypt, of course. Returns
# a {GPGME::Data} object which can then be read.
#
# @param text
# The object that will be signed. Must be something that can be converted
# to {GPGME::Data}.
#
# @param [Hash] options
# Optional parameters.
# * +:signer+ sign identifier to sign the text with. Will use the first
# key it finds if none specified.
# * +:output+ if specified, it will write the output into it. It will be
# converted to a {GPGME::Data} object, so it could be a file for example.
# * +:mode+ Desired type of signature. Options are:
# - +GPGME::SIG_MODE_NORMAL+ for a normal signature. The default one if
# not specified.
# - +GPGME::SIG_MODE_DETACH+ for a detached signature
# - +GPGME::SIG_MODE_CLEAR+ for a cleartext signature
# * Any other option accepted by {GPGME::Ctx.new}
#
# @return [GPGME::Data] a {GPGME::Data} that can be read.
#
# @example normal sign
# crypto.sign "Hi there"
#
# @example outputing to a file
# file = File.open("text.sign", "w+")
# crypto.sign "Hi there", :options => file
#
# @example doing a detached signature
# crypto.sign "Hi there", :mode => GPGME::SIG_MODE_DETACH
#
# @example specifying the signer
# crypto.sign "Hi there", :signer => "mrsimo@example.com"
#
# @raise [GPGME::Error::UnusableSecretKey] TODO don't know when
def sign(text, options = {})
options = @default_options.merge options
plain = Data.new(text)
output = Data.new(options[:output])
mode = options[:mode] || GPGME::SIG_MODE_NORMAL
GPGME::Ctx.new(options) do |ctx|
if options[:signer]
signers = Key.find(:secret, options[:signer], :sign)
ctx.add_signer(*signers)
end
begin
ctx.sign(plain, output, mode)
rescue GPGME::Error::UnusableSecretKey => exc
exc.keys = ctx.sign_result.invalid_signers
raise exc
end
end
output.seek(0)
output
end
# Verifies a previously signed element
#
# crypto.verify sig, options, &block
#
# Must have the proper keys available.
#
# @param sig
# The signature itself. Must be possible to convert into a {GPGME::Data}
# object, so can be a file.
#
# @param [Hash] options
# * +:signed_text+ if the sign is detached, then must be the plain text
# for which the signature was created.
# * +:output+ where to store the result of the signature. Will be
# converted to a {GPGME::Data} object.
# * Any other option accepted by {GPGME::Ctx.new}
#
# @param &block
# In the block all the signatures are yielded, so one could verify them.
# See examples.
#
# @return [GPGME::Data] unless the sign is detached, the {GPGME::Data}
# object with the plain text. If the sign is detached, will return nil.
#
# @example simple verification
# sign = crypto.sign("Hi there")
# data = crypto.verify(sign) { |signature| signature.valid? }
# data.read # => "Hi there"
#
# @example saving output to file
# sign = crypto.sign("Hi there")
# out = File.open("test.asc", "w+")
# crypto.verify(sign, :output => out) {|signature| signature.valid?}
# out.read # => "Hi there"
#
# @example verifying a detached signature
# sign = crypto.detach_sign("Hi there")
# # Will fail
# crypto.verify(sign) { |signature| signature.valid? }
# # Will succeed
# crypto.verify(sign, :signed_text => "hi there") do |signature|
# signature.valid?
# end
#
def verify(sig, options = {})
options = @default_options.merge options
sig = Data.new(sig)
signed_text = Data.new(options[:signed_text])
output = Data.new(options[:output]) unless options[:signed_text]
GPGME::Ctx.new(options) do |ctx|
ctx.verify(sig, signed_text, output)
ctx.verify_result.signatures.each do |signature|
yield signature
end
end
if output
output.seek(0)
output
end
end
# Clearsigns an element
#
# crypto.clearsign text, options
#
# Same functionality of {.sign} only doing clearsigns by default.
#
def clearsign(text, options = {})
sign text, options.merge(:mode => GPGME::SIG_MODE_CLEAR)
end
# Creates a detached signature of an element
#
# crypto.detach_sign text, options
#
# Same functionality of {.sign} only doing detached signs by default.
#
def detach_sign(text, options = {})
sign text, options.merge(:mode => GPGME::SIG_MODE_DETACH)
end
##
# Allows calling of methods directly in the module without the need to
# create a new instance.
def self.method_missing(method, *args, &block)
if GPGME::Crypto.instance_methods(false).include?(method)
crypto = GPGME::Crypto.new
crypto.send method, *args, &block
else
super
end
end
end # module Crypto
end # module GPGME
gpgme-2.0.16/lib/gpgme/io_callbacks.rb 0000644 0000041 0000041 00000000575 13234766063 017550 0 ustar www-data www-data module GPGME
class IOCallbacks
def initialize(io)
@io = io
end
def read(hook, length)
@io.read(length)
end
def write(hook, buffer, length)
@io.write(buffer[0 .. length])
end
def seek(hook, offset, whence)
return @io.pos if offset == 0 && whence == IO::SEEK_CUR
@io.seek(offset, whence)
@io.pos
end
end
end
gpgme-2.0.16/lib/gpgme/version.rb 0000644 0000041 0000041 00000000132 13234766063 016614 0 ustar www-data www-data module GPGME
# The version of GPGME ruby binding you are using
VERSION = "2.0.16"
end
gpgme-2.0.16/lib/gpgme/sub_key.rb 0000644 0000041 0000041 00000002615 13234766063 016600 0 ustar www-data www-data module GPGME
class SubKey
private_class_method :new
attr_reader :pubkey_algo, :length, :keyid, :fpr
alias fingerprint fpr
include KeyCommon
def timestamp
case @timestamp
when -1, 0
# FIXME: add a special value for invalid timestamp, or throw an error
return nil
else
return Time.at(@timestamp)
end
end
def expires?
@expires != 0
end
def expires
expires? ? Time.at(@expires) : nil
end
def expired
expires? && @expires < Time.now.to_i
end
def sha
(@fpr || @keyid)[-8 .. -1]
end
PUBKEY_ALGO_LETTERS = {
PK_RSA => "R",
PK_ELG_E => "g",
PK_ELG => "G",
PK_DSA => "D"
}
def pubkey_algo_letter
PUBKEY_ALGO_LETTERS[@pubkey_algo] || "?"
end
def inspect
sprintf("#<#{self.class} %s %4d%s/%s %s trust=%s, capability=%s>",
secret? ? 'ssc' : 'sub',
length,
pubkey_algo_letter,
(@fpr || @keyid)[-8 .. -1],
timestamp.strftime('%Y-%m-%d'),
trust.inspect,
capability.inspect)
end
def to_s
sprintf("%s %4d%s/%s %s\n",
secret? ? 'ssc' : 'sub',
length,
pubkey_algo_letter,
(@fpr || @keyid)[-8 .. -1],
timestamp.strftime('%Y-%m-%d'))
end
end
end
gpgme-2.0.16/lib/gpgme/key.rb 0000644 0000041 0000041 00000015655 13234766063 015737 0 ustar www-data www-data module GPGME
##
# A ruby representation of a public or a secret key.
#
# Every key has two instances of {GPGME::SubKey}, accessible through
# {.subkeys}, and with a {.primary_subkey} where most attributes are
# derived from, like the +fingerprint+.
#
# Also, every key has at least a {GPGME::UserID}, accessible through
# {.uids}, with a {.primary_uid}, where other attributes are derived from,
# like +email+ or +name+
class Key
private_class_method :new
attr_reader :keylist_mode, :protocol, :owner_trust
attr_reader :issuer_serial, :issuer_name, :chain_id
attr_reader :subkeys, :uids
include KeyCommon
class << self
##
# Returns an array of {GPGME::Key} objects that match the parameters.
# * +secret+ set to +:secret+ to get only secret keys, or to +:public+ to
# get only public keys.
# * +keys_or_names+ an array or an item that can be either {GPGME::Key}
# elements, or string identifiers like the email or the sha. Leave
# blank to get all.
# * +purposes+ get only keys that are usable for any of these purposes.
# See {GPGME::Key} for a list of possible key capabilities.
#
# @example
# GPGME::Key.find :secret # => first secret key found
#
# @example
# GPGME::Key.find(:public, "mrsimo@example.com")
# # => return only public keys that match mrsimo@example.com
#
# @example
# GPGME::Key.find(:public, "mrsimo@example.com", :sign)
# # => return the public keys that match mrsimo@example.com and are
# # capable of signing
def find(secret, keys_or_names = nil, purposes = [])
secret = (secret == :secret)
keys_or_names = [""] if keys_or_names.nil? || (keys_or_names.is_a?(Array) && keys_or_names.empty?)
keys_or_names = [keys_or_names].flatten
purposes = [purposes].flatten.compact.uniq
keys = []
keys_or_names.each do |key_or_name|
case key_or_name
when Key then keys << key_or_name
when String
GPGME::Ctx.new do |ctx|
keys += ctx.keys(key_or_name, secret).select do |k|
k.usable_for?(purposes)
end
end
end
end
keys
end
def get(fingerprint)
Ctx.new do |ctx|
ctx.get_key(fingerprint)
end
end
# Exports public keys
#
# GPGME::Key.export pattern, options
#
# Private keys cannot be exported due to GPGME restrictions.
#
# @param pattern
# Identifier of the key to export.
#
# @param [Hash] options
# * +:output+ specify where to write the key to. It will be converted to
# a {GPGME::Data}, so it could be a file, for example.
# * Any other option accepted by {GPGME::Ctx.new}
#
# @return [GPGME::Data] the exported key.
#
# @example
# key = GPGME::Key.export "mrsimo@example.com"
#
# @example writing to a file
# out = File.open("my.key", "w+")
# GPGME::Key.export "mrsimo@example.com", :output => out
#
def export(pattern, options = {})
output = Data.new(options[:output])
GPGME::Ctx.new(options) do |ctx|
ctx.export_keys(pattern, output)
end
output.seek(0)
output
end
# Imports a key
#
# GPGME::Key.import keydata, options
#
# @param keydata
# The key to import. It will be converted to a {GPGME::Data} object,
# so could be a file, for example.
# @param options
# Any other option accepted by {GPGME::Ctx.new}
#
# @example
# GPGME::Key.import(File.open("my.key"))
#
def import(keydata, options = {})
GPGME::Ctx.new(options) do |ctx|
ctx.import_keys(Data.new(keydata))
ctx.import_result
end
end
end
##
# Exports this key. Accepts the same options as {GPGME::Ctx.new}, and
# +options[:output]+, where you can specify something that can become a
# {GPGME::Data}, where the output will go.
#
# @example
# key.export(:armor => true)
# # => GPGME::Data you can read with ASCII armored format
#
# @example
# file = File.open("key.asc", "w+")
# key.export(:output => file)
# # => the key will be written to the file.
#
def export(options = {})
Key.export self.sha, options
end
##
# Delete this key. If it's public, and has a secret one it will fail unless
# +allow_secret+ is specified as true.
def delete!(allow_secret = false)
GPGME::Ctx.new do |ctx|
ctx.delete_key self, allow_secret
end
end
##
# Returns true if the key has an expiry date else false
def expires?
primary_subkey.expires?
end
##
# Returns the expiry date for this key
def expires
primary_subkey.expires
end
##
# Returns true if the key is expired
def expired
subkeys.any?(&:expired)
end
def primary_subkey
@primary_subkey ||= subkeys.first
end
##
# Short descriptive value. Can be used to identify the key.
def sha
primary_subkey.sha
end
##
# Longer descriptive value. Can be used to identify the key.
def fingerprint
primary_subkey.fingerprint
end
##
# Returns the main {GPGME::UserID} for this key.
def primary_uid
uids.first
end
##
# Returns the email for this key.
def email
primary_uid.email
end
##
# Returns the issuer name for this key.
def name
primary_uid.name
end
##
# Returns the issuer comment for this key.
def comment
primary_uid.comment
end
def ==(another_key)
self.class === another_key and fingerprint == another_key.fingerprint
end
def inspect
sprintf("#<#{self.class} %s %4d%s/%s %s trust=%s, owner_trust=%s, \
capability=%s, subkeys=%s, uids=%s>",
primary_subkey.secret? ? 'sec' : 'pub',
primary_subkey.length,
primary_subkey.pubkey_algo_letter,
primary_subkey.fingerprint[-8 .. -1],
primary_subkey.timestamp.strftime('%Y-%m-%d'),
trust.inspect,
VALIDITY_NAMES[@owner_trust].inspect,
capability.inspect,
subkeys.inspect,
uids.inspect)
end
def to_s
primary_subkey = subkeys[0]
s = sprintf("%s %4d%s/%s %s\n",
primary_subkey.secret? ? 'sec' : 'pub',
primary_subkey.length,
primary_subkey.pubkey_algo_letter,
primary_subkey.fingerprint[-8 .. -1],
primary_subkey.timestamp.strftime('%Y-%m-%d'))
uids.each do |user_id|
s << "uid\t\t#{user_id.name} <#{user_id.email}>\n"
end
subkeys.each do |subkey|
s << subkey.to_s
end
s
end
end
end
gpgme-2.0.16/lib/gpgme/key_common.rb 0000644 0000041 0000041 00000002241 13234766063 017272 0 ustar www-data www-data module GPGME
module KeyCommon
##
# Returns nil if the trust is valid.
# Returns one of +:revoked+, +:expired+, +:disabled+, +:invalid+
def trust
return :revoked if @revoked == 1
return :expired if @expired == 1
return :disabled if @disabled == 1
return :invalid if @invalid == 1
end
##
# Array of capabilities for this key. It can contain any combination of
# +:encrypt+, +:sign+, +:certify+ or +:authenticate+
def capability
caps = []
caps << :encrypt if @can_encrypt == 1
caps << :sign if @can_sign == 1
caps << :certify if @can_certify == 1
caps << :authenticate if @can_authenticate == 1
caps
end
##
# Checks if the key is capable of all of these actions. If empty array
# is passed then will return true.
#
# Returns false if the keys trust has been invalidated.
def usable_for?(purposes)
unless purposes.kind_of? Array
purposes = [purposes]
end
return false if [:revoked, :expired, :disabled, :invalid].include? trust
return (purposes - capability).empty?
end
def secret?
@secret == 1
end
end
end
gpgme-2.0.16/lib/gpgme/data.rb 0000644 0000041 0000041 00000013172 13234766063 016050 0 ustar www-data www-data module GPGME
##
# A class whose purpose is to unify the way we work with the data (both input
# and output). Most of the calls expect instances of this class, or will try
# to create one from your parameters.
#
# Read the {#read}, {#write} and {#seek} methods for the most commonly used
# methods.
class Data
BLOCK_SIZE = 4096
class << self
##
# We implement +self.new+ instead of initialize because objects are actually
# instantiated through the C API with stuff like +gpgme_data_new+.
#
# We try to create a {GPGME::Data} smartly depending on the object passed, and if
# another {GPGME::Data} object is passed, it just returns it, so when in
# doubt, you can always pass a {GPGME::Data} object.
#
# @example empty
# data = GPGME::Data.new
# data.write("stuff")
#
# @example from a string
# data = GPGME::Data.new("From a string")
#
# @example from a file
# data = GPGME::Data.new(File.open("secure.pass"))
#
# @example from a file descriptor
# data = GPGME::Data.new(0) # Standard input
# data = GPGME::Data.new(1) # Standard output
#
# file = File.open("secure.pass")
# data = GPGME::Data.new(file.fileno) # file descriptor
#
def new(object = nil)
if object.nil?
empty!
elsif object.is_a?(Data)
object
elsif object.is_a?(Integer)
from_fd(object)
elsif object.respond_to? :to_str
from_str(object.to_str)
elsif object.respond_to? :to_io
from_io(object.to_io)
elsif object.respond_to? :open
from_io(object.open)
elsif defined?(StringIO) and object.is_a?(StringIO)
from_io(object)
end
end
# Create a new instance with an empty buffer.
def empty!
rdh = []
err = GPGME::gpgme_data_new(rdh)
exc = GPGME::error_to_exception(err)
raise exc if exc
rdh.first
end
# Create a new instance with internal buffer.
def from_str(string)
rdh = []
err = GPGME::gpgme_data_new_from_mem(rdh, string, string.bytesize)
exc = GPGME::error_to_exception(err)
raise exc if exc
rdh.first
end
# Create a new instance associated with a given IO.
def from_io(io)
from_callbacks(IOCallbacks.new(io))
end
# Create a new instance from the specified file descriptor.
def from_fd(fd)
rdh = []
err = GPGME::gpgme_data_new_from_fd(rdh, fd)
exc = GPGME::error_to_exception(err)
raise exc if exc
rdh.first
end
# Create a new instance from the specified callbacks.
def from_callbacks(callbacks, hook_value = nil)
rdh = []
err = GPGME::gpgme_data_new_from_cbs(rdh, callbacks, hook_value)
exc = GPGME::error_to_exception(err)
raise exc if exc
rdh.first
end
end # class << self
# Read at most +length+ bytes from the data object, or to the end
# of file if +length+ is omitted or is +nil+.
#
# @example
# data = GPGME::Data.new("From a string")
# data.read # => "From a string"
#
# @example
# data = GPGME::Data.new("From a string")
# data.read(4) # => "From"
#
def read(length = nil)
if length
GPGME::gpgme_data_read(self, length)
else
buf = String.new
loop do
s = GPGME::gpgme_data_read(self, BLOCK_SIZE)
break unless s
buf << s
end
buf
end
end
##
# Seek to a given +offset+ in the data object according to the
# value of +whence+.
#
# @example going to the beginning of the buffer after writing something
# data = GPGME::Data.new("Some data")
# data.read # => "Some data"
# data.read # => ""
# data.seek 0
# data.read # => "Some data"
#
def seek(offset, whence = IO::SEEK_SET)
GPGME::gpgme_data_seek(self, offset, IO::SEEK_SET)
end
##
# Writes +length+ bytes from +buffer+ into the data object.
# Writes the full buffer if no length passed.
#
# @example
# data = GPGME::Data.new
# data.write "hola"
# data.seek 0
# data.read # => "hola"
#
# @example
# data = GPGME::Data.new
# data.write "hola", 2
# data.seek 0
# data.read # => "ho"
#
def write(buffer, length = buffer.length)
GPGME::gpgme_data_write(self, buffer, length)
end
##
# Return the encoding of the underlying data.
def encoding
GPGME::gpgme_data_get_encoding(self)
end
##
# Sets the encoding for this buffer. Accepts only values in one of the
# DATA_ENCODING_* constants.
#
# @raise [GPGME::Error::InvalidValue] if the value isn't accepted.
def encoding=(encoding)
err = GPGME::gpgme_data_set_encoding(self, encoding)
exc = GPGME::error_to_exception(err)
raise exc if exc
encoding
end
##
# Return the file name of the underlying data.
def file_name
GPGME::gpgme_data_get_file_name(self)
end
##
# Sets the file name for this buffer.
#
# @raise [GPGME::Error::InvalidValue] if the value isn't accepted.
def file_name=(file_name)
err = GPGME::gpgme_data_set_file_name(self, file_name)
exc = GPGME::error_to_exception(err)
raise exc if exc
file_name
end
##
# Return the entire content of the data object as string.
def to_s
pos = seek(0, IO::SEEK_CUR)
begin
seek(0)
read
ensure
seek(pos)
end
end
end
end
gpgme-2.0.16/lib/gpgme/constants.rb 0000644 0000041 0000041 00000023411 13234766063 017150 0 ustar www-data www-data module GPGME
ATTR_ALGO = GPGME_ATTR_ALGO
ATTR_CAN_CERTIFY = GPGME_ATTR_CAN_CERTIFY
ATTR_CAN_ENCRYPT = GPGME_ATTR_CAN_ENCRYPT
ATTR_CAN_SIGN = GPGME_ATTR_CAN_SIGN
ATTR_CHAINID = GPGME_ATTR_CHAINID
ATTR_COMMENT = GPGME_ATTR_COMMENT
ATTR_CREATED = GPGME_ATTR_CREATED
ATTR_EMAIL = GPGME_ATTR_EMAIL
ATTR_ERRTOK = GPGME_ATTR_ERRTOK
ATTR_EXPIRE = GPGME_ATTR_EXPIRE
ATTR_FPR = GPGME_ATTR_FPR
ATTR_ISSUER = GPGME_ATTR_ISSUER
ATTR_IS_SECRET = GPGME_ATTR_IS_SECRET
ATTR_KEYID = GPGME_ATTR_KEYID
ATTR_KEY_CAPS = GPGME_ATTR_KEY_CAPS
ATTR_KEY_DISABLED = GPGME_ATTR_KEY_DISABLED
ATTR_KEY_EXPIRED = GPGME_ATTR_KEY_EXPIRED
ATTR_KEY_INVALID = GPGME_ATTR_KEY_INVALID
ATTR_KEY_REVOKED = GPGME_ATTR_KEY_REVOKED
ATTR_LEN = GPGME_ATTR_LEN
ATTR_LEVEL = GPGME_ATTR_LEVEL
ATTR_NAME = GPGME_ATTR_NAME
ATTR_OTRUST = GPGME_ATTR_OTRUST
ATTR_SERIAL = GPGME_ATTR_SERIAL
ATTR_SIG_STATUS = GPGME_ATTR_SIG_STATUS
ATTR_SIG_SUMMARY = GPGME_ATTR_SIG_SUMMARY
ATTR_TYPE = GPGME_ATTR_TYPE
ATTR_UID_INVALID = GPGME_ATTR_UID_INVALID
ATTR_UID_REVOKED = GPGME_ATTR_UID_REVOKED
ATTR_USERID = GPGME_ATTR_USERID
ATTR_VALIDITY = GPGME_ATTR_VALIDITY
DATA_ENCODING_ARMOR = GPGME_DATA_ENCODING_ARMOR
DATA_ENCODING_BASE64 = GPGME_DATA_ENCODING_BASE64
DATA_ENCODING_BINARY = GPGME_DATA_ENCODING_BINARY
DATA_ENCODING_NONE = GPGME_DATA_ENCODING_NONE
ENCRYPT_ALWAYS_TRUST = GPGME_ENCRYPT_ALWAYS_TRUST
if defined?(GPGME_ENCRYPT_NO_ENCRYPT_TO)
ENCRYPT_NO_ENCRYPT_TO = GPGME_ENCRYPT_NO_ENCRYPT_TO
end
IMPORT_NEW = GPGME_IMPORT_NEW
IMPORT_SECRET = GPGME_IMPORT_SECRET
IMPORT_SIG = GPGME_IMPORT_SIG
IMPORT_SUBKEY = GPGME_IMPORT_SUBKEY
IMPORT_UID = GPGME_IMPORT_UID
KEYLIST_MODE_EXTERN = GPGME_KEYLIST_MODE_EXTERN
KEYLIST_MODE_LOCAL = GPGME_KEYLIST_MODE_LOCAL
KEYLIST_MODE_SIGS = GPGME_KEYLIST_MODE_SIGS
KEYLIST_MODE_VALIDATE = GPGME_KEYLIST_MODE_VALIDATE
if defined?(GPGME_KEYLIST_MODE_SIG_NOTATIONS)
KEYLIST_MODE_SIG_NOTATIONS = GPGME_KEYLIST_MODE_SIG_NOTATIONS
end
if defined?(GPGME_KEYLIST_MODE_EPHEMERAL)
KEYLIST_MODE_EPHEMERAL = GPGME_KEYLIST_MODE_EPHEMERAL
end
if defined?(GPGME_KEYLIST_MODE_WITH_SECRET)
KEYLIST_MODE_WITH_SECRET = GPGME_KEYLIST_MODE_WITH_SECRET
end
MD_CRC24_RFC2440 = GPGME_MD_CRC24_RFC2440
MD_CRC32 = GPGME_MD_CRC32
MD_CRC32_RFC1510 = GPGME_MD_CRC32_RFC1510
MD_HAVAL = GPGME_MD_HAVAL
MD_MD2 = GPGME_MD_MD2
MD_MD4 = GPGME_MD_MD4
MD_MD5 = GPGME_MD_MD5
MD_RMD160 = GPGME_MD_RMD160
MD_SHA1 = GPGME_MD_SHA1
MD_SHA256 = GPGME_MD_SHA256
if defined?(MD_SHA224)
MD_SHA224 = GPGME_MD_SHA224
end
MD_SHA384 = GPGME_MD_SHA384
MD_SHA512 = GPGME_MD_SHA512
MD_TIGER = GPGME_MD_TIGER
if defined?(gpgme_set_pinentry_mode)
PINENTRY_MODE_DEFAULT = GPGME_PINENTRY_MODE_DEFAULT
PINENTRY_MODE_ASK = GPGME_PINENTRY_MODE_ASK
PINENTRY_MODE_CANCEL = GPGME_PINENTRY_MODE_CANCEL
PINENTRY_MODE_ERROR = GPGME_PINENTRY_MODE_ERROR
PINENTRY_MODE_LOOPBACK = GPGME_PINENTRY_MODE_LOOPBACK
PINENTRY_MODE_NAMES = {
PINENTRY_MODE_DEFAULT => :default,
PINENTRY_MODE_ASK => :ask,
PINENTRY_MODE_CANCEL => :cancel,
PINENTRY_MODE_ERROR => :error,
PINENTRY_MODE_LOOPBACK => :loopback
}
end
PK_DSA = GPGME_PK_DSA
PK_ELG = GPGME_PK_ELG
PK_ELG_E = GPGME_PK_ELG_E
PK_RSA = GPGME_PK_RSA
if defined?(GPGME_PK_ECC)
PK_ECC = GPGME_PK_ECC
end
PROTOCOL_CMS = GPGME_PROTOCOL_CMS
PROTOCOL_OpenPGP = GPGME_PROTOCOL_OpenPGP
SIGSUM_BAD_POLICY = GPGME_SIGSUM_BAD_POLICY
SIGSUM_CRL_MISSING = GPGME_SIGSUM_CRL_MISSING
SIGSUM_CRL_TOO_OLD = GPGME_SIGSUM_CRL_TOO_OLD
SIGSUM_GREEN = GPGME_SIGSUM_GREEN
SIGSUM_KEY_EXPIRED = GPGME_SIGSUM_KEY_EXPIRED
SIGSUM_KEY_MISSING = GPGME_SIGSUM_KEY_MISSING
SIGSUM_KEY_REVOKED = GPGME_SIGSUM_KEY_REVOKED
SIGSUM_RED = GPGME_SIGSUM_RED
SIGSUM_SIG_EXPIRED = GPGME_SIGSUM_SIG_EXPIRED
SIGSUM_SYS_ERROR = GPGME_SIGSUM_SYS_ERROR
SIGSUM_VALID = GPGME_SIGSUM_VALID
SIG_MODE_CLEAR = GPGME_SIG_MODE_CLEAR
SIG_MODE_DETACH = GPGME_SIG_MODE_DETACH
SIG_MODE_NORMAL = GPGME_SIG_MODE_NORMAL
SIG_STAT_BAD = GPGME_SIG_STAT_BAD
SIG_STAT_DIFF = GPGME_SIG_STAT_DIFF
SIG_STAT_ERROR = GPGME_SIG_STAT_ERROR
SIG_STAT_GOOD = GPGME_SIG_STAT_GOOD
SIG_STAT_GOOD_EXP = GPGME_SIG_STAT_GOOD_EXP
SIG_STAT_GOOD_EXPKEY = GPGME_SIG_STAT_GOOD_EXPKEY
SIG_STAT_NOKEY = GPGME_SIG_STAT_NOKEY
SIG_STAT_NONE = GPGME_SIG_STAT_NONE
SIG_STAT_NOSIG = GPGME_SIG_STAT_NOSIG
STATUS_ABORT = GPGME_STATUS_ABORT
STATUS_ALREADY_SIGNED = GPGME_STATUS_ALREADY_SIGNED
STATUS_BADARMOR = GPGME_STATUS_BADARMOR
STATUS_BADMDC = GPGME_STATUS_BADMDC
STATUS_BADSIG = GPGME_STATUS_BADSIG
STATUS_BAD_PASSPHRASE = GPGME_STATUS_BAD_PASSPHRASE
STATUS_BEGIN_DECRYPTION = GPGME_STATUS_BEGIN_DECRYPTION
STATUS_BEGIN_ENCRYPTION = GPGME_STATUS_BEGIN_ENCRYPTION
STATUS_BEGIN_STREAM = GPGME_STATUS_BEGIN_STREAM
STATUS_DECRYPTION_FAILED = GPGME_STATUS_DECRYPTION_FAILED
STATUS_DECRYPTION_OKAY = GPGME_STATUS_DECRYPTION_OKAY
STATUS_DELETE_PROBLEM = GPGME_STATUS_DELETE_PROBLEM
STATUS_ENC_TO = GPGME_STATUS_ENC_TO
STATUS_END_DECRYPTION = GPGME_STATUS_END_DECRYPTION
STATUS_END_ENCRYPTION = GPGME_STATUS_END_ENCRYPTION
STATUS_END_STREAM = GPGME_STATUS_END_STREAM
STATUS_ENTER = GPGME_STATUS_ENTER
STATUS_EOF = GPGME_STATUS_EOF
STATUS_ERRMDC = GPGME_STATUS_ERRMDC
STATUS_ERROR = GPGME_STATUS_ERROR
STATUS_ERRSIG = GPGME_STATUS_ERRSIG
STATUS_EXPKEYSIG = GPGME_STATUS_EXPKEYSIG
STATUS_EXPSIG = GPGME_STATUS_EXPSIG
STATUS_FILE_DONE = GPGME_STATUS_FILE_DONE
STATUS_FILE_ERROR = GPGME_STATUS_FILE_ERROR
STATUS_FILE_START = GPGME_STATUS_FILE_START
STATUS_GET_BOOL = GPGME_STATUS_GET_BOOL
STATUS_GET_HIDDEN = GPGME_STATUS_GET_HIDDEN
STATUS_GET_LINE = GPGME_STATUS_GET_LINE
STATUS_GOODMDC = GPGME_STATUS_GOODMDC
STATUS_GOODSIG = GPGME_STATUS_GOODSIG
STATUS_GOOD_PASSPHRASE = GPGME_STATUS_GOOD_PASSPHRASE
STATUS_GOT_IT = GPGME_STATUS_GOT_IT
STATUS_IMPORTED = GPGME_STATUS_IMPORTED
STATUS_IMPORT_RES = GPGME_STATUS_IMPORT_RES
STATUS_INV_RECP = GPGME_STATUS_INV_RECP
STATUS_KEYEXPIRED = GPGME_STATUS_KEYEXPIRED
STATUS_KEYREVOKED = GPGME_STATUS_KEYREVOKED
STATUS_KEY_CREATED = GPGME_STATUS_KEY_CREATED
STATUS_LEAVE = GPGME_STATUS_LEAVE
STATUS_MISSING_PASSPHRASE = GPGME_STATUS_MISSING_PASSPHRASE
STATUS_NEED_PASSPHRASE = GPGME_STATUS_NEED_PASSPHRASE
STATUS_NEED_PASSPHRASE_SYM = GPGME_STATUS_NEED_PASSPHRASE_SYM
STATUS_NODATA = GPGME_STATUS_NODATA
STATUS_NOTATION_DATA = GPGME_STATUS_NOTATION_DATA
STATUS_NOTATION_NAME = GPGME_STATUS_NOTATION_NAME
STATUS_NO_PUBKEY = GPGME_STATUS_NO_PUBKEY
STATUS_NO_RECP = GPGME_STATUS_NO_RECP
STATUS_NO_SECKEY = GPGME_STATUS_NO_SECKEY
if defined?(GPGME_STATUS_PKA_TRUST_BAD)
STATUS_PKA_TRUST_BAD = GPGME_STATUS_PKA_TRUST_BAD
end
if defined?(GPGME_STATUS_PKA_TRUST_GOOD)
STATUS_PKA_TRUST_GOOD = GPGME_STATUS_PKA_TRUST_GOOD
end
if defined?(GPGME_STATUS_PLAINTEXT_LENGTH)
STATUS_PLAINTEXT_LENGTH = GPGME_STATUS_PLAINTEXT_LENGTH
end
if defined?(GPGME_STATUS_MOUNTPOINT)
STATUS_MOUNTPOINT = GPGME_STATUS_MOUNTPOINT
end
if defined?(GPGME_STATUS_PINENTRY_LAUNCHED)
STATUS_PINENTRY_LAUNCHED = GPGME_STATUS_PINENTRY_LAUNCHED
end
if defined?(GPGME_STATUS_ATTRIBUTE)
STATUS_ATTRIBUTE = GPGME_STATUS_ATTRIBUTE
end
if defined?(GPGME_STATUS_BEGIN_SIGNING)
STATUS_BEGIN_SIGNING = GPGME_STATUS_BEGIN_SIGNING
end
if defined?(GPGME_STATUS_KEY_NOT_CREATED)
STATUS_KEY_NOT_CREATED = GPGME_STATUS_KEY_NOT_CREATED
end
STATUS_POLICY_URL = GPGME_STATUS_POLICY_URL
STATUS_PROGRESS = GPGME_STATUS_PROGRESS
STATUS_RSA_OR_IDEA = GPGME_STATUS_RSA_OR_IDEA
STATUS_SESSION_KEY = GPGME_STATUS_SESSION_KEY
STATUS_SHM_GET = GPGME_STATUS_SHM_GET
STATUS_SHM_GET_BOOL = GPGME_STATUS_SHM_GET_BOOL
STATUS_SHM_GET_HIDDEN = GPGME_STATUS_SHM_GET_HIDDEN
STATUS_SHM_INFO = GPGME_STATUS_SHM_INFO
STATUS_SIGEXPIRED = GPGME_STATUS_SIGEXPIRED
STATUS_SIG_CREATED = GPGME_STATUS_SIG_CREATED
STATUS_SIG_ID = GPGME_STATUS_SIG_ID
STATUS_TRUNCATED = GPGME_STATUS_TRUNCATED
STATUS_TRUST_FULLY = GPGME_STATUS_TRUST_FULLY
STATUS_TRUST_MARGINAL = GPGME_STATUS_TRUST_MARGINAL
STATUS_TRUST_NEVER = GPGME_STATUS_TRUST_NEVER
STATUS_TRUST_ULTIMATE = GPGME_STATUS_TRUST_ULTIMATE
STATUS_TRUST_UNDEFINED = GPGME_STATUS_TRUST_UNDEFINED
STATUS_UNEXPECTED = GPGME_STATUS_UNEXPECTED
STATUS_USERID_HINT = GPGME_STATUS_USERID_HINT
STATUS_VALIDSIG = GPGME_STATUS_VALIDSIG
VALIDITY_FULL = GPGME_VALIDITY_FULL
VALIDITY_MARGINAL = GPGME_VALIDITY_MARGINAL
VALIDITY_NEVER = GPGME_VALIDITY_NEVER
VALIDITY_ULTIMATE = GPGME_VALIDITY_ULTIMATE
VALIDITY_UNDEFINED = GPGME_VALIDITY_UNDEFINED
VALIDITY_UNKNOWN = GPGME_VALIDITY_UNKNOWN
PROTOCOL_NAMES = {
PROTOCOL_OpenPGP => :OpenPGP,
PROTOCOL_CMS => :CMS
}
if defined?(GPGME_PROTOCOL_ASSUAN)
PROTOCOL_ASSUAN = GPGME_PROTOCOL_ASSUAN
PROTOCOL_NAMES[PROTOCOL_ASSUAN] = :ASSUAN
end
if defined?(GPGME_PROTOCOL_SPAWN)
PROTOCOL_SPAWN = GPGME_PROTOCOL_SPAWN
PROTOCOL_NAMES[PROTOCOL_SPAWN] = :SPAWN
SPAWN_DETACHED = GPGME_SPAWN_DETACHED
SPAWN_ALLOW_SET_FG = GPGME_SPAWN_ALLOW_SET_FG
end
if defined?(GPGME_EXPORT_MODE_EXTERN)
EXPORT_MODE_EXTERN = GPGME_EXPORT_MODE_EXTERN
end
if defined?(GPGME_EXPORT_MODE_MINIMAL)
EXPORT_MODE_MINIMAL = GPGME_EXPORT_MODE_MINIMAL
end
if defined?(GPGME_EXPORT_MODE_SECRET)
EXPORT_MODE_SECRET = GPGME_EXPORT_MODE_SECRET
EXPORT_MODE_RAW = GPGME_EXPORT_MODE_RAW
EXPORT_MODE_PKCS12 = GPGME_EXPORT_MODE_PKCS12
end
KEYLIST_MODE_NAMES = {
KEYLIST_MODE_LOCAL => :local,
KEYLIST_MODE_EXTERN => :extern,
KEYLIST_MODE_SIGS => :sigs,
KEYLIST_MODE_VALIDATE => :validate
}
VALIDITY_NAMES = {
VALIDITY_UNKNOWN => :unknown,
VALIDITY_UNDEFINED => :undefined,
VALIDITY_NEVER => :never,
VALIDITY_MARGINAL => :marginal,
VALIDITY_FULL => :full,
VALIDITY_ULTIMATE => :ultimate
}
end
gpgme-2.0.16/lib/gpgme/misc.rb 0000644 0000041 0000041 00000002727 13234766063 016076 0 ustar www-data www-data module GPGME
class EngineInfo
private_class_method :new
attr_reader :protocol, :file_name, :version, :req_version, :home_dir
alias required_version req_version
end
class VerifyResult
private_class_method :new
attr_reader :signatures
end
class Recipient
private_class_method :new
attr_reader :pubkey_algo, :keyid, :status
end
class DecryptResult
private_class_method :new
attr_reader :unsupported_algorithm, :wrong_key_usage
attr_reader :recipients, :file_name
end
class SignResult
private_class_method :new
attr_reader :invalid_signers, :signatures
end
class EncryptResult
private_class_method :new
attr_reader :invalid_recipients
end
class InvalidKey
private_class_method :new
attr_reader :fpr, :reason
alias fingerprint fpr
end
class NewSignature
private_class_method :new
attr_reader :type, :pubkey_algo, :hash_algo, :sig_class, :fpr
alias fingerprint fpr
def timestamp
Time.at(@timestamp)
end
end
class ImportStatus
private_class_method :new
attr_reader :fpr, :result, :status
alias fingerprint fpr
end
class ImportResult
private_class_method :new
attr_reader :considered, :no_user_id, :imported, :imported_rsa, :unchanged
attr_reader :new_user_ids, :new_sub_keys, :new_signatures, :new_revocations
attr_reader :secret_read, :secret_imported, :secret_unchanged
attr_reader :not_imported, :imports
end
end
gpgme-2.0.16/lib/gpgme/error.rb 0000644 0000041 0000041 00000003546 13234766063 016274 0 ustar www-data www-data module GPGME
class Error < StandardError
def initialize(error)
@error = error
end
attr_reader :error
# Return the error code.
#
# The error code indicates the type of an error, or the reason why
# an operation failed.
def code
GPGME::gpgme_err_code(@error)
end
# Return the error source.
#
# The error source has not a precisely defined meaning. Sometimes
# it is the place where the error happened, sometimes it is the
# place where an error was encoded into an error value. Usually
# the error source will give an indication to where to look for
# the problem. This is not always true, but it is attempted to
# achieve this goal.
def source
GPGME::gpgme_err_source(@error)
end
# Return a description of the error code.
def message
GPGME::gpgme_strerror(@error)
end
class General < self; end
class InvalidValue < self; end
class UnusablePublicKey < self
attr_accessor :keys
end
class UnusableSecretKey < self
attr_accessor :keys
end
class NoData < self; end
class Conflict < self; end
class NotImplemented < self; end
class DecryptFailed < self; end
class BadPassphrase < self; end
class Canceled < self; end
class InvalidEngine < self; end
class AmbiguousName < self; end
class WrongKeyUsage < self
attr_accessor :key_usage
end
class CertificateRevoked < self; end
class CertificateExpired < self; end
class NoCRLKnown < self; end
class NoPolicyMatch < self; end
class NoSecretKey < self; end
class MissingCertificate < self; end
class BadCertificateChain < self; end
class UnsupportedAlgorithm < self
attr_accessor :algorithm
end
class BadSignature < self; end
class NoPublicKey < self; end
class InvalidVersion < self; end
end
end
gpgme-2.0.16/test/ 0000755 0000041 0000041 00000000000 13234766064 013721 5 ustar www-data www-data gpgme-2.0.16/test/key_test.rb 0000644 0000041 0000041 00000013635 13234766064 016105 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'test_helper'
describe GPGME::Key do
before do
skip unless ensure_keys GPGME::PROTOCOL_OpenPGP
end
it "has certain attributes" do
key = GPGME::Key.find(:secret).first
[:keylist_mode, :protocol, :owner_trust, :issuer_serial,
:issuer_name, :chain_id, :subkeys, :uids].each do |attrib|
assert key.respond_to?(attrib), "Key doesn't respond to #{attrib}"
end
end
it "won't allow the creation of GPGME::Key's without the C API" do
assert_raises NoMethodError do
GPGME::Key.new
end
end
it "can compare one with another even though if they're not the same object" do
key1 = GPGME::Key.find(:secret).first
key2 = GPGME::Key.find(:secret).first
refute_equal key1.object_id, key2.object_id
assert_equal key1, key2
end
it "can compare a key with any other object" do
key1 = GPGME::Key.find(:secret).first
refute_equal key1, nil
end
describe :find do
it "should return all by default" do
keys = GPGME::Key.find :secret
assert_instance_of GPGME::Key, keys.first
assert 0 < keys.size
end
it "returns an array even if you pass only one descriptor" do
keys_one = GPGME::Key.find(:secret, KEYS.first[:sha]).map{|key| key.subkeys.map(&:keyid)}
keys_array = GPGME::Key.find(:secret, [KEYS.first[:sha]]).map{|key| key.subkeys.map(&:keyid)}
assert_equal keys_one, keys_array
end
it "returns only secret keys if told to do so" do
keys = GPGME::Key.find :secret
assert keys.all?(&:secret?)
end
it "returns only public keys if told to do so" do
keys = GPGME::Key.find :public
assert keys.none?(&:secret?)
end
it "filters by capabilities" do
GPGME::Key.any_instance.stubs(:usable_for?).returns(false)
keys = GPGME::Key.find :public, "", :wadusing
assert keys.empty?
end
end
describe :export do
# Testing the lazy way with expectations. I think tests in
# the Ctx class are enough.
it "exports any key that matches the pattern" do
GPGME::Ctx.any_instance.expects(:export_keys).with("", anything)
GPGME::Key.export("")
end
it "exports any key that matches the pattern, can specify output" do
data = GPGME::Data.new
GPGME::Ctx.any_instance.expects(:export_keys).with("wadus", data)
ret = GPGME::Key.export("wadus", :output => data)
assert_equal data, ret
end
it "can specify options for Ctx" do
GPGME::Ctx.expects(:new).with(:armor => true).yields(mock(:export_keys => true))
GPGME::Key.export("wadus", :armor => true)
end
end
describe "#export" do
it "can export from the key instance" do
key = GPGME::Key.find(:public).first
GPGME::Key.expects(:export).with(key.sha, {})
key.export
end
it "can export from the key instance passing variables" do
key = GPGME::Key.find(:public).first
GPGME::Key.expects(:export).with(key.sha, {:armor => true})
key.export :armor => true
end
end
describe :import do
it "can import keys" do
data = GPGME::Data.new
GPGME::Ctx.any_instance.expects(:import_keys).with(data)
GPGME::Ctx.any_instance.expects(:import_result).returns("wadus")
assert_equal "wadus", GPGME::Key.import(data)
end
it "can specify options for Ctx" do
GPGME::Ctx.expects(:new).with(:armor => true).yields(mock(:import_keys => true, :import_result => true))
GPGME::Key.import("wadus", :armor => true)
end
end
# describe :trust do
# it "returns :revoked if it is so"
# it "returns :expired if it is expired"
# it "returns :disabled if it is so"
# it "returns :invalid if it is so"
# it "returns nil otherwise"
# end
# describe :capability do
# it "returns an array of possible capabilities"
# end
# describe :secret? do
# "returns true/false depending on the instance variable"
# end
describe :usable_for? do
it "checks for the capabilities of the key and returns true if it matches all" do
key = GPGME::Key.find(:secret).first
key.stubs(:capability).returns([:encrypt, :sign])
assert key.usable_for?([])
key.stubs(:capability).returns([:encrypt, :sign])
assert key.usable_for?([:encrypt])
key.stubs(:capability).returns([:encrypt, :sign])
refute key.usable_for?([:certify])
end
it "returns false if the key is expired or revoked or disabled or disabled" do
key = GPGME::Key.find(:secret).first
key.stubs(:trust).returns(:revoked)
key.stubs(:capability).returns([:encrypt, :sign])
refute key.usable_for?([:encrypt])
end
end
describe :delete! do
it "deletes the key itself and its secret one if called with true" do
begin
key = KEYS.first
GPGME::Key.find(:public, key[:sha]).first.delete!(true)
assert_empty GPGME::Key.find(:public, key[:sha])
assert_empty GPGME::Key.find(:secret, key[:sha])
ensure
import_key key
end
end
it "raises GPGME::Error::Conflict if we're deleting a key that is secret" do
key = KEYS.first
assert_raises GPGME::Error::Conflict do
GPGME::Key.find(:secret, key[:sha]).first.delete!
end
refute_empty GPGME::Key.find(:secret, key[:sha])
end
end
it "knows if the key is expired" do
key = GPGME::Key.find(:secret).first
refute key.expired
with_key EXPIRED_KEY do
key = GPGME::Key.find(:secret, EXPIRED_KEY[:sha]).first
assert key.expired
end
end
it "returns the expiry date of the first subkey" do
key = GPGME::Key.find(:secret).first
subkey = key.primary_subkey
subkey.expects(:expired).returns(true)
assert key.expired
end
describe :inspect do
it "can be inspected" do
key = GPGME::Key.find(:secret).first
key.inspect
end
end
describe :to_s do
it "can be coerced into a String" do
key = GPGME::Key.find(:secret).first
key.to_s
end
end
end
gpgme-2.0.16/test/crypto_test.rb 0000644 0000041 0000041 00000017043 13234766064 016632 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'test_helper'
require 'tempfile'
describe GPGME::Crypto do
before do
skip unless ensure_keys GPGME::PROTOCOL_OpenPGP
end
describe "default options functionality" do
it "allows operation from instances normally" do
crypto = GPGME::Crypto.new
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
end
it "can set default options when using the instance way" do
crypto = GPGME::Crypto.new :always_trust => true
encrypted = crypto.encrypt TEXT[:plain], :recipients => KEYS.first[:sha]
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
end
it "but they can still be overwritten" do
crypto = GPGME::Crypto.new :always_trust => false
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
end
end
describe "roundtrip encryption/decryption" do
it "does the roundtrip encrypting" do
crypto = GPGME::Crypto.new
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :recipients => KEYS.first[:sha]
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
end
it "does so even with armored encrypted stuff" do
crypto = GPGME::Crypto.new
encrypted = crypto.encrypt TEXT[:plain], :always_trust => true, :armor => true
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
end
end
describe :encrypt do
it "should raise an error if the recipients aren't trusted" do
assert_raises GPGME::Error::UnusablePublicKey do
GPGME::Crypto.new.encrypt TEXT[:plain]
end
end
it "doesn't raise an error and returns something when encrypting nothing" do
data = GPGME::Crypto.new.encrypt nil, :always_trust => true
refute_empty data.read
data = GPGME::Crypto.new.encrypt "", :always_trust => true
refute_empty data.read
end
it "can specify which key(s) to use for encrypting with a string" do
crypto = GPGME::Crypto.new :always_trust => true
key = KEYS.last
encrypted = crypto.encrypt TEXT[:plain], :recipients => key[:sha]
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
remove_key key
encrypted.seek 0
assert_raises GPGME::Error::DecryptFailed do
crypto.decrypt(encrypted)
end
import_key key
end
it "can specify which key to use for encrypting with a Key object" do
crypto = GPGME::Crypto.new :always_trust => true
key = KEYS.last
real_key = GPGME::Key.find(:public, key[:sha]).first
encrypted = crypto.encrypt TEXT[:plain], :recipients => real_key
assert_equal TEXT[:plain], crypto.decrypt(encrypted).read
remove_key key
encrypted.seek 0
assert_raises GPGME::Error::DecryptFailed do
crypto.decrypt(encrypted)
end
import_key key
end
it "can also sign at the same time" do
crypto = GPGME::Crypto.new :always_trust => true
encrypted = crypto.encrypt TEXT[:plain], :sign => true
signatures = 0
crypto.verify(encrypted) do |signature|
assert_instance_of GPGME::Signature, signature
signatures += 1
end
assert_equal 1, signatures
end
it "can be signed by more than one person" do
crypto = GPGME::Crypto.new :always_trust => true
encrypted = crypto.encrypt TEXT[:plain], :sign => true, :signers => KEYS.map{|k| k[:sha]}
signatures = 0
crypto.verify(encrypted) do |signature|
assert_instance_of GPGME::Signature, signature
signatures += 1
end
assert_equal 4, signatures
end
it "outputs to a file if specified" do
crypto = GPGME::Crypto.new :always_trust => true
file = Tempfile.new "test"
crypto.encrypt TEXT[:plain], :output => file
file_contents = file.read
file.seek 0
refute_empty file_contents
assert_equal TEXT[:plain], crypto.decrypt(file).read
end
# TODO find how to test
# it "raises GPGME::Error::UnusablePublicKey"
# it "raises GPGME::Error::UnusableSecretKey"
end
describe "symmetric encryption/decryption" do
it "requires a password to encrypt" do
assert_raises GPGME::Error::BadPassphrase do
GPGME::Crypto.new.encrypt TEXT[:plain], :symmetric => true
end
end
it "requires a password to decrypt" do
crypto = GPGME::Crypto.new
encrypted_data = crypto.encrypt TEXT[:plain],
:symmetric => true, :password => "gpgme"
assert_raises GPGME::Error::BadPassphrase do
crypto.decrypt encrypted_data
end
end
it "can encrypt and decrypt with the same password" do
crypto = GPGME::Crypto.new :symmetric => true, :password => "gpgme"
encrypted_data = crypto.encrypt TEXT[:plain]
plain = crypto.decrypt encrypted_data
assert_equal "Hi there", plain.read
end
it "but breaks with different ones" do
crypto = GPGME::Crypto.new
encrypted_data = crypto.encrypt TEXT[:plain],
:symmetric => true, :password => "gpgme"
assert_raises GPGME::Error::DecryptFailed do
crypto.decrypt encrypted_data, :password => "wrong one"
end
end
end
describe :decrypt do
it "decrypts encrypted stuff" do
assert_equal TEXT[:plain], GPGME::Crypto.new.decrypt(TEXT[:encrypted]).read
end
it "will not get into the signatures block if there's none" do
GPGME::Crypto.new.decrypt(TEXT[:encrypted]) do |signature|
flunk "If I'm here means there was some signature"
end
pass
end
it "will get signature elements if the encrypted thing was signed" do
signatures = 0
GPGME::Crypto.new.decrypt(TEXT[:signed]) do |signature|
assert_instance_of GPGME::Signature, signature
signatures += 1
end
assert_equal 1, signatures
end
it "writes to the output if passed" do
buffer = GPGME::Data.new
GPGME::Crypto.new.decrypt(TEXT[:encrypted], :output => buffer)
assert_equal TEXT[:plain], buffer.read
end
# TODO find ways to test this
# it "raises UnsupportedAlgorithm"
# it "raises WrongKeyUsage"
it "raises DecryptFailed when the decrypting key isn't available" do
assert_raises GPGME::Error::DecryptFailed do
GPGME::Crypto.new.decrypt(TEXT[:unavailable])
end
end
end
describe :sign do
it "signs normal strings" do
crypto = GPGME::Crypto.new
signatures = 0
sign = crypto.sign "Hi there"
crypto.verify(sign) do |signature|
assert_instance_of GPGME::Signature, signature
assert signature.valid?
signatures += 1
end
assert_equal 1, signatures
end
# TODO Find how to import an expired public key
# it "raises an error if trying to sign with an expired key" do
# with_key EXPIRED_KEY do
# crypto = GPGME::Crypto.new
# assert_raises GPGME::Error::General do
# sign = crypto.sign "Hi there", :signer => EXPIRED_KEY[:sha]
# end
# end
# end
it "selects who to sign for" do
crypto = GPGME::Crypto.new
sign = crypto.sign "Hi there", :signer => KEYS.last[:sha]
key = GPGME::Key.get(KEYS.last[:sha])
signatures = 0
crypto.verify(sign) do |signature|
assert_instance_of GPGME::Signature, signature
assert_equal key, signature.key
signatures += 1
end
assert_equal 1, signatures
end
end
end
gpgme-2.0.16/test/files/ 0000755 0000041 0000041 00000000000 13234766064 015023 5 ustar www-data www-data gpgme-2.0.16/test/files/testkey_sec.gpg 0000644 0000041 0000041 00000006312 13234766064 020046 0 ustar www-data www-data -----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
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
u+DMAdQjSwNi0/7uqGbnAyZuRpBaKWJu9s4YRdU=
=kQA4
-----END PGP PRIVATE KEY BLOCK-----
gpgme-2.0.16/test/files/testkey_pub.gpg 0000644 0000041 0000041 00000006112 13234766064 020060 0 ustar www-data www-data -----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
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
=T/Ce
-----END PGP PUBLIC KEY BLOCK-----
gpgme-2.0.16/test/ctx_test.rb 0000644 0000041 0000041 00000027703 13234766064 016114 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'test_helper'
describe GPGME::Ctx do
before do
skip unless ensure_keys GPGME::PROTOCOL_OpenPGP
end
it "can instantiate" do
assert_instance_of GPGME::Ctx, GPGME::Ctx.new
end
it "doesn't close itself" do
GPGME.expects(:gpgme_release).never
GPGME::Ctx.new
end
it "closes itself if called with a block" do
GPGME.expects(:gpgme_release).with(anything)
GPGME::Ctx.new { |ctx| }
end
it "can be closed with the release method" do
GPGME.expects(:gpgme_release).with(anything)
ctx = GPGME::Ctx.new
ctx.release
end
describe :new do
# We consider :armor, :protocol, :textmode and :keylist_mode as tested
# with the other tests of this file. Here we test the rest
it ":password sets the password for the key" do
with_key PASSWORD_KEY do
input = GPGME::Data.new(TEXT[:passwored])
output = GPGME::Data.new
GPGME::Ctx.new(:password => 'gpgme') do |ctx|
ctx.decrypt_verify input, output
output.seek 0
assert_equal "Hi there", output.read.chomp
recipients = ctx.decrypt_result.recipients
assert_equal 1, recipients.size
recipient_key = ctx.get_key(recipients.first.keyid)
key = ctx.get_key(PASSWORD_KEY[:sha])
assert_equal recipient_key, key
end
end
end
it ":passphrase_callback sets the callback for the password" do
def test_pass_func(obj,par2,par3,prev_was_bad,fd)
# prev_was_bad is 0 the first time, 1 the rest
if @var == 0
assert_equal 0, prev_was_bad
else
assert_equal 1, prev_was_bad
end
@var += 1
io = IO.for_fd(fd, 'w')
io.puts "wrong pasword"
io.flush
end
def with_correct_pass_func(obj,par2,par3,prev_was_bad,fd)
io = IO.for_fd(fd, 'w')
io.puts "gpgme"
io.flush
end
with_key PASSWORD_KEY do
input = GPGME::Data.new(TEXT[:passwored])
output = GPGME::Data.new
@var = 0
assert_raises GPGME::Error::BadPassphrase do
GPGME::Ctx.new(:passphrase_callback => method(:test_pass_func)) do |ctx|
ctx.decrypt_verify input, output
end
end
# Since we request the key 3 times, we should've gone through the
# callback 3 times.
assert_equal 3, @var
input.seek 0
output.seek 0
# Shouldn't crash
GPGME::Ctx.new(:passphrase_callback => method(:with_correct_pass_func)) do |ctx|
ctx.decrypt_verify input, output
end
end
end
it ":passphrase_callback_value passes a value to the callback function" do
def checking_value(value,par2,par3,par4,fd)
assert_equal "superman", value
io = IO.for_fd(fd, 'w')
io.puts "gpgme"
io.flush
end
with_key PASSWORD_KEY do
input = GPGME::Data.new(TEXT[:passwored])
output = GPGME::Data.new
options = {
:passphrase_callback => method(:checking_value),
:passphrase_callback_value => "superman"
}
GPGME::Ctx.new(options) do |ctx|
ctx.decrypt_verify input, output
end
end
end
# TODO Don't know how to use them yet
# it ":progress_callback"
# it ":progress_callback_value"
end
describe :decrypt_result do
it "returns the list of encyption recipients" do
cipher = GPGME::Data.new(KEY_1_ENCRYPTED)
output = GPGME::Data.new
GPGME::Ctx.new do |ctx|
ctx.decrypt_verify(cipher, output)
assert_equal 1, ctx.decrypt_result.recipients.size
end
end
it "should not segfault" do
cipher = GPGME::Data.new(KEY_1_ENCRYPTED)
ouput = GPGME::Data.new
GPGME::Ctx.new do |ctx|
assert_raises ArgumentError do
ctx.decrypt_result
end
end
end
end
describe :armor do
it "sets false by default" do
ctx = GPGME::Ctx.new
refute ctx.armor
end
it "can set" do
ctx = GPGME::Ctx.new
ctx.armor = true
assert ctx.armor
end
it "can set and get armor" do
ctx = GPGME::Ctx.new(:armor => false)
refute ctx.armor
ctx = GPGME::Ctx.new(:armor => true)
assert ctx.armor
end
end
describe :protocol do
it "sets 0 by default" do
ctx = GPGME::Ctx.new
assert_equal 0, ctx.protocol
end
it "can set" do
ctx = GPGME::Ctx.new
ctx.protocol = 1
assert_equal 1, ctx.protocol
end
it "can set and get protocol" do
ctx = GPGME::Ctx.new(:protocol => GPGME::PROTOCOL_OpenPGP)
assert_equal GPGME::PROTOCOL_OpenPGP, ctx.protocol
end
it "doesn't allow just any value" do
assert_raises GPGME::Error::InvalidValue do
ctx = GPGME::Ctx.new(:protocol => -200)
end
end
end
describe :textmode do
it "sets false by default" do
ctx = GPGME::Ctx.new
refute ctx.textmode
end
it "can set" do
ctx = GPGME::Ctx.new
ctx.textmode = true
assert ctx.textmode
end
it "can set and get textmode" do
ctx = GPGME::Ctx.new(:textmode => false)
refute ctx.textmode
ctx = GPGME::Ctx.new(:textmode => true)
assert ctx.textmode
end
end
describe :keylist_mode do
it "sets local by default" do
ctx = GPGME::Ctx.new
assert_equal GPGME::KEYLIST_MODE_LOCAL, ctx.keylist_mode
end
it "can set and get" do
ctx = GPGME::Ctx.new(:keylist_mode => GPGME::KEYLIST_MODE_SIGS)
assert_equal GPGME::KEYLIST_MODE_SIGS, ctx.keylist_mode
end
it "can set" do
ctx = GPGME::Ctx.new
ctx.keylist_mode = GPGME::KEYLIST_MODE_SIGS
assert_equal GPGME::KEYLIST_MODE_SIGS, ctx.keylist_mode
end
it "allows the four possible values" do
[GPGME::KEYLIST_MODE_LOCAL, GPGME::KEYLIST_MODE_EXTERN,
GPGME::KEYLIST_MODE_SIGS, GPGME::KEYLIST_MODE_VALIDATE].each do |mode|
GPGME::Ctx.new(:keylist_mode => mode)
end
end
# It's not crashing?
# it "crashes with other values" do
# GPGME::Ctx.new(:keylist_mode => -200)
# end
end
# describe :set_passphrase_callback do
# def test_pass_func(par1,par2,par3,par4,par5)
# par1
# end
# test "it sets the passphrase"
# end
describe "keylist operations" do
it "can return all of the keys" do
ctx = GPGME::Ctx.new
keys = ctx.keys
ctx.release
assert keys.size >= 4
KEYS.each do |key|
assert keys.map(&:email).include?(key[:sha])
end
end
it "can return keys filtering by a pattern" do
ctx = GPGME::Ctx.new
keys = ctx.keys(KEYS.first[:sha])
ctx.release
assert_equal 1, keys.size
assert_equal KEYS.first[:sha], keys.first.email
end
it "can return only secret keys" do
ctx = GPGME::Ctx.new
keys = ctx.keys(KEYS.first[:sha], true)
ctx.release
assert keys.all?(&:secret?)
end
it "can return only public keys" do
ctx = GPGME::Ctx.new
keys = ctx.keys(KEYS.first[:sha], false)
ctx.release
refute keys.any?(&:secret?)
end
it "returns only public keys by default" do
ctx = GPGME::Ctx.new
keys = ctx.keys(KEYS.first[:sha])
ctx.release
refute keys.any?(&:secret?)
end
it "can iterate through them returning only public keys" do
GPGME::Ctx.new do |ctx|
ctx.each_key do |key|
assert_instance_of GPGME::Key, key
refute key.secret?
end
end
end
it "can iterate through them getting only secret ones" do
GPGME::Ctx.new do |ctx|
ctx.each_key("", true) do |key|
assert_instance_of GPGME::Key, key
assert key.secret?
end
end
end
it "can iterate through them filtering by pattern" do
num = 0
GPGME::Ctx.new do |ctx|
ctx.each_key(KEYS.first[:sha]) do |key|
assert_instance_of GPGME::Key, key
assert_equal KEYS.first[:sha], key.email
num += 1
end
end
assert_equal 1, num
end
it "can get only a specific key" do
GPGME::Ctx.new do |ctx|
key = ctx.get_key(KEYS.first[:sha])
assert_instance_of GPGME::Key, key
assert_equal KEYS.first[:sha], key.email
end
end
end
describe "key generation" do
it "generates a key according to specifications" do
key = <<-RUBY
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 1024
Name-Real: Key Testér
Name-Comment: with some comments
Name-Email: test_generation@example.com
Expire-Date: 0
Passphrase: wadus
RUBY
if RUBY_VERSION > "1.9"
assert_equal key.encoding, Encoding::UTF_8
end
keys_amount = GPGME::Key.find(:public).size
GPGME::Ctx.new do |ctx|
ctx.generate_key(key.chomp)
end
assert_equal keys_amount + 1, GPGME::Key.find(:public).size
GPGME::Key.find(:public, "test_generation@example.com").each do |k|
if RUBY_VERSION > "1.9"
# Make sure UTF-8 in and UTF-8 out.
assert_equal "Key Testér", k.name
assert_equal k.name.encoding, Encoding::UTF_8
end
k.delete!(true)
end
end
end
describe "key export/import" do
it "exports and imports all keys when passing an empty string" do
original_keys = GPGME::Key.find(:public)
export = ""
GPGME::Ctx.new do |ctx|
export = ctx.export_keys("")
end
export.seek(0)
GPGME::Key.find(:public).each{|k| k.delete!(true)}
assert_equal 0, GPGME::Key.find(:public).size
result = GPGME::Key.import(export)
current_keys = GPGME::Key.find(:public)
assert_equal original_keys.size, current_keys.size
assert_equal result.imports.size, current_keys.size
assert result.imports.all?{|import| import.status == 1}
assert_equal original_keys.map(&:sha), original_keys.map(&:sha)
import_keys # If the test fails for some reason, it won't break others.
end
it "exports only one key" do
original_keys = GPGME::Key.find(:public)
key = original_keys.first
export = ""
GPGME::Ctx.new do |ctx|
export = ctx.export_keys(key.sha)
end
export.seek(0)
key.delete!(true)
result = GPGME::Key.import(export)
assert_equal 1, result.imports.size
import = result.imports.first
imported_key = GPGME::Key.find(:public, import.fpr).first
assert_equal key.sha, imported_key.sha
assert_equal key.email, imported_key.email
import_keys # If the test fails for some reason, it won't break others.
end
it "imports keys and can get a result object" do
without_key KEYS.last do
public_amount = GPGME::Key.find(:public).size
secret_amount = GPGME::Key.find(:secret).size
result = nil
GPGME::Ctx.new do |ctx|
ctx.import_keys(GPGME::Data.new(KEYS.last[:public]))
ctx.import_keys(GPGME::Data.new(KEYS.last[:secret]))
result = ctx.import_result
end
assert_equal secret_amount + 1, GPGME::Key.find(:secret).size
assert_equal public_amount + 1, GPGME::Key.find(:public).size
assert_instance_of GPGME::ImportResult, result
assert_instance_of GPGME::ImportStatus, result.imports.first
end
end
end
describe "deleting/editing of keys" do
it "can delete keys" do
original_keys = GPGME::Key.find(:public)
key = original_keys.first
GPGME::Ctx.new do |ctx|
ctx.delete_key key, true
end
assert_empty GPGME::Key.find(:public, key.sha)
import_keys
end
it "raises error if there's a secret key attached but secret key deletion isn't marked" do
original_keys = GPGME::Key.find(:public)
key = original_keys.first
assert_raises GPGME::Error::Conflict do
GPGME::Ctx.new do |ctx|
ctx.delete_key key
end
end
end
end
# Don't know how to test or use edit_key and edit_card
end
gpgme-2.0.16/test/test_helper.rb 0000644 0000041 0000041 00000003640 13234766064 016567 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'coveralls'
Coveralls.wear!
# include compiled gpgme_n.bundle
tmp_dir = File.join(File.dirname(__FILE__), '..', 'tmp')
$:.unshift(tmp_dir) if File.directory?(tmp_dir)
# this interfers otherwise with our tests
ENV.delete('GPG_AGENT_INFO')
require 'rubygems'
require 'bundler/setup'
require 'minitest/autorun'
require 'minitest/spec'
require 'minitest/pride'
require 'mocha'
require 'gpgme'
if RUBY_VERSION.split('.').first.to_i > 1
require 'byebug'
else
require 'ruby-debug'
end
require File.dirname(__FILE__) + "/support/resources"
def import_keys
KEYS.each do |key|
import_key(key)
end
end
def import_key(key, only = :all)
GPGME::Key.import(key[:public]) unless only == :secret
GPGME::Key.import(key[:secret]) unless only == :public
end
def remove_keys
KEYS.each do |key|
remove_key(key)
end
end
def remove_all_keys
GPGME::Key.find(:public).each do |k|
k.delete!(true)
end
GPGME::Key.find(:secret).each do |k|
k.delete!(true)
end
end
def remove_key(key)
GPGME::Key.find(:public, key[:sha]).each do |k|
k.delete!(true)
end
GPGME::Key.find(:secret, key[:sha]).each do |k|
k.delete!(true)
end
end
def with_key(key, only = :all, &block)
import_key key, only
begin
yield
ensure
remove_key key
end
end
def without_key(key, &block)
remove_key key
begin
yield
ensure
import_key key
end
end
DIRS = []
at_exit do
DIRS.each do |dir|
FileUtils.remove_entry dir
end
DIRS.clear
end
def ensure_keys(proto)
return false unless GPGME::Engine.check_version proto
case proto
when GPGME::PROTOCOL_OpenPGP
# We use a different home directory for the keys to not disturb current
# installation
require 'tmpdir'
if DIRS.empty?
dir = Dir.mktmpdir
GPGME::Engine.home_dir = dir
DIRS.push(dir)
remove_all_keys
import_keys
end
true
else
return false
end
end
gpgme-2.0.16/test/gpgme_test.rb 0000644 0000041 0000041 00000000245 13234766064 016405 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'test_helper'
describe GPGME do
it "should pass" do
assert true
end
it "should also pass" do
assert true
end
end
gpgme-2.0.16/test/signature_test.rb 0000644 0000041 0000041 00000002727 13234766064 017316 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'test_helper'
describe GPGME::Signature do
before do
skip unless ensure_keys GPGME::PROTOCOL_OpenPGP
end
it "#valid? is true when the signature is valid" do
crypto = GPGME::Crypto.new
signatures = 0
sign = crypto.sign "Hi there"
crypto.verify(sign) do |signature|
assert_instance_of GPGME::Signature, signature
assert signature.valid?
refute signature.expired_signature?
refute signature.expired_key?
refute signature.revoked_key?
refute signature.bad?
refute signature.no_key?
signatures += 1
end
assert_equal 1, signatures
end
it "#expired_key? is true when the key has expired" do
with_key EXPIRED_KEY do
crypto = GPGME::Crypto.new
signatures = 0
crypto.verify(TEXT[:expired_key_sign]) do |signature|
assert_instance_of GPGME::Signature, signature
refute signature.valid?
refute signature.expired_signature?
assert signature.expired_key?
refute signature.revoked_key?
refute signature.bad?
refute signature.no_key?
signatures += 1
end
assert_equal 1, signatures
end
end
# TODO Find how to test these
# it "#expired_signature? is true when the signature has expired"
# it "#revoked_key? is true when the key has been revoked"
# it "#bad? is true when the signature is bad"
# it "#no_key? is true when we don't have the key to verify the signature"
end
gpgme-2.0.16/test/support/ 0000755 0000041 0000041 00000000000 13234766064 015435 5 ustar www-data www-data gpgme-2.0.16/test/support/resources.rb 0000644 0000041 0000041 00000062311 13234766064 017777 0 ustar www-data www-data key1_public = <<-RUBY
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
mI0ETbL4sAEEANBs/WsOxRCLdsW1h8LKGT6eJpAs6omGV/G7TJnMsk92BUIub3oZ
9oRC1L0l4EKB6o8/vULziT815dbbVxwQIOyDXEqP4sokRxjSNNkpPb+RuIjdmP6e
SJ2NxCxV/GxLhjZZTHG5SPH4Gei3TtdiHMHoar0rwEcVdS693K/6Ww8ZABEBAAG0
IVRlc3QgbnVtYmVyIDEgPHRlc3QxQGV4YW1wbGUuY29tPoi4BBMBAgAiBQJNsviw
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRD7yLd2W11cdyxOA/4gPEK1
qF8bp0YJfc91Ob/J70N5gNuO06AeBa8o6MHTUheCp5CMFD8RISDegsiYey3O+Wvk
rg+BmIQWqGTglDIDOM8B1Bmc+T+C0sRwIwmHqDo5a9mR2QnlcFqZ3SNV5MdxDUa4
GJk4LbUj/JwU2nR8Z4eA7OC1LjOexFKAfLX657iNBE2y+LABBAC9UqqJKhUDqhDy
dPfMsQYOA14QPcx8cx5hsUyLsZOm9RGxNdw8fRItfMZWfwB69pr4KicVYxC5YyxM
+KpVBHr+QoTxEn/KcMdude44Y104F33oZ2wiCpMzCu1ZW/OFIoWuEMHXLyIXJD1C
VVMkbiOjwRxo3otPSGijrhcmS0PkJQARAQABiJ8EGAECAAkFAk2y+LACGwwACgkQ
+8i3dltdXHdf/wQAiIKzJaUg5S+EU3lr9XZPIDZeNcQpKf2JaLu4uFVPtKGtZIYa
F00HCKom4OHkrFfdVdr1948xet9sAt2PV9GoIAV8pkBwqs02Wz6mxJpgsnAuEJTM
Pwe30z4usZ5kM/PDMCpN+A9vkzYieyxquvkul2W7VfzLftx81UexyoFnJ9I=
=u++L
-----END PGP PUBLIC KEY BLOCK-----
RUBY
key1_secret = <<-RUBY
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
lQHYBE2y+LABBADQbP1rDsUQi3bFtYfCyhk+niaQLOqJhlfxu0yZzLJPdgVCLm96
GfaEQtS9JeBCgeqPP71C84k/NeXW21ccECDsg1xKj+LKJEcY0jTZKT2/kbiI3Zj+
nkidjcQsVfxsS4Y2WUxxuUjx+Bnot07XYhzB6Gq9K8BHFXUuvdyv+lsPGQARAQAB
AAP7B/aQucP7HP5LF9OEn+6t8hHDn5YLvEc3pHV3atfihyfXRxee7DoXjFGWWbIG
WbF8104Zing4tJjNUtJssgE0FMDq1EmcDjYjMPwNUrmaPhlbsnCpqtiIdjsJbdsh
39Kl8MG1EDSInwq2ToVyQGfFywClUYYQmqCbVEmaeoocZMUCAORfTj82VyelybRV
p6JYvg9oIBuUZh6RUFsWtXVxs5pqNKN70/5SnFzIaukY3NBVqDQ1iOcLQmbYBCPn
/gDTDa0CAOmj8HhXeNq7Aof9qqvzh2YZhuyoc4BtAYGs9KJj/oLEkTkIVlcIM5yp
tYRzdQZT8RQRRD8sUAC1W2BtX+033J0CAIKIvFJnRqwhwQn+eBG7f20lPqNA8ceU
yz1vMOPZ/puOulsxuH/g0vGJ6i364Aph7UdnTjl3lCXosqmxHHgJbp+eorQhVGVz
dCBudW1iZXIgMSA8dGVzdDFAZXhhbXBsZS5jb20+iLgEEwECACIFAk2y+LACGwMG
CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPvIt3ZbXVx3LE4D/iA8QrWoXxun
Rgl9z3U5v8nvQ3mA247ToB4FryjowdNSF4KnkIwUPxEhIN6CyJh7Lc75a+SuD4GY
hBaoZOCUMgM4zwHUGZz5P4LSxHAjCYeoOjlr2ZHZCeVwWpndI1Xkx3ENRrgYmTgt
tSP8nBTadHxnh4Ds4LUuM57EUoB8tfrnnQHYBE2y+LABBAC9UqqJKhUDqhDydPfM
sQYOA14QPcx8cx5hsUyLsZOm9RGxNdw8fRItfMZWfwB69pr4KicVYxC5YyxM+KpV
BHr+QoTxEn/KcMdude44Y104F33oZ2wiCpMzCu1ZW/OFIoWuEMHXLyIXJD1CVVMk
biOjwRxo3otPSGijrhcmS0PkJQARAQABAAP9FheQ5duewyQzwQ8sIVsg4T68WbnU
ZEtMpsq5K23n1Goxi9PEpNxVZDB0toAwbqjbMY09rU23lGKBt2OnAK+6qEBRkdoh
9HjgVckVy/efqp2FGSFs79yv4m3EvK/lRnMhFE9/LktayhZsiKZaRmR5evqyCoRh
vWAccOngO4ww+WECAMtq4M9tTeab6SI5nH0W/RfGicH701cacRkM4KDXxs8STmTy
qugEERpuK2fTA4DjBRjv1oF+Ld5mAhExtH7gktUCAO5DFNdfdW6TifdHPpLqyRgP
7DpZlcOqVIbVwtcPrk+3nVASQ4qvCggMJT36Fif9EZqqkIIZeWQxGADZAtkblBEC
AKb9RHZNxaCY+Ax2AkI5fhwMpA/PEcyBSVes+mmlA4Zneq8YJciUFPwKdOaHU6yc
8LiuaTDNjuHLJpUZrWa2N5mdK4ifBBgBAgAJBQJNsviwAhsMAAoJEPvIt3ZbXVx3
X/8EAIiCsyWlIOUvhFN5a/V2TyA2XjXEKSn9iWi7uLhVT7ShrWSGGhdNBwiqJuDh
5KxX3VXa9fePMXrfbALdj1fRqCAFfKZAcKrNNls+psSaYLJwLhCUzD8Ht9M+LrGe
ZDPzwzAqTfgPb5M2Inssarr5Lpdlu1X8y37cfNVHscqBZyfS
=1FOM
-----END PGP PRIVATE KEY BLOCK-----
RUBY
key2_public = <<-RUBY
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
mI0ETbLs3gEEAK+Y1z0MgmwP3M5d+tGTVHKBcoi5KRJKYSbWX2Kus+vVCLvohbuf
b41pNcQh3QWY9DtnvEyFHoVnrb6fktFjbiU0y89qv7vsbleR8O5Mt82urjlsVCqp
kI3a4l4+T6a1iLR2QSF04v2e0PKECIFpSLmnjAiZUyYPaseT/h+r84uZABEBAAG0
IVRlc3QgbnVtYmVyIDIgPHRlc3QyQGV4YW1wbGUuY29tPoi4BBMBAgAiBQJNsuze
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRA5K+LKd9ZlZu/8A/9Ql6Qf
m2LS49QZUcV4sqvUrYRqhHrXxH4NpfvcErE2aOolEtLYpIf1wFun6Cmjc9TLacW6
vJGaKfafFqQ5I4bGDAwkVik6keU58HM7vxBmWafNh2KhwzNQXIJ9yORYSfUoWGWS
yT/JDJk7mSFcSCyRKXc10PcnLUkoWwSnUtdN0biNBE2y7N4BBAC8lQFu/ru0hNvn
NpeMkkxZhgNVSaIfR7My5zznCwaVQzud6ZH2zcQUmfina12vRNqA7TBaQyc/Ebsd
z/PkMCCXPDyaUgp1EJKdVd5nUnO/6yEinf1zkI5kpYd/dKSMcbMIOdEUeBsOUR7Y
g6uPoNK40Dwmg3vH5rsSEcrupzWeHwARAQABiJ8EGAECAAkFAk2y7N4CGwwACgkQ
OSviynfWZWZJ4gP+KI9e9fjpCVLXVA3mH459+kWwNOMWrTImk0CXFGIS/sm7cODu
zLJNS32muxaHisbIDVcK/vac3wksa0DjgiIQa08yI40F7V9y6FsS/PxvPO8Hi9AX
AjUk9I7RWu3E2loIHgYeTBwXyKLmWr5ZVfpX6KvIa4Y3MTRnE0x6+woeT90=
=DclA
-----END PGP PUBLIC KEY BLOCK-----
RUBY
key2_secret = <<-RUBY
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
lQHYBE2y7N4BBACvmNc9DIJsD9zOXfrRk1RygXKIuSkSSmEm1l9irrPr1Qi76IW7
n2+NaTXEId0FmPQ7Z7xMhR6FZ62+n5LRY24lNMvPar+77G5XkfDuTLfNrq45bFQq
qZCN2uJePk+mtYi0dkEhdOL9ntDyhAiBaUi5p4wImVMmD2rHk/4fq/OLmQARAQAB
AAP8D1bzoZeGyrQhis0asMV1NHoStHcxa3HANi12wHcIzG6sMEcmLJ9nVjQFUISR
S3CC0HA12rzrz0VhABSuVZihKd2dEVFQiY2BfpZ0j6XVoUF/w+wB1KJ73et6AsyY
f3iLtu/OTQeOC68EKi08yogRu/EFo25vVOhyIhQF5rDMkxECANKDcGkmJsZZr7+V
GqJS5mHLHy7aI7aN8f4uEQx/QXK3MW5PA12KgNc91kT8MbTYueI8/yNZe/DtBpji
yUelpZECANWJ/9L2gEgXDggcYe5+f7kYzxhkEjypX3Ewkza7CRWUqS2Bz8GzmFls
8s+UhiyWJAMZ/uNUy6YPawUoTnZyYYkCANCoKZfKw0zHypZ7HhH1znmdQkte+sJc
G9604Os1RGVO6Tu30fCd7AaStPc4qfAPwJDDaSCLzMN9U6VGROaW9Iyff7QhVGVz
dCBudW1iZXIgMiA8dGVzdDJAZXhhbXBsZS5jb20+iLgEEwECACIFAk2y7N4CGwMG
CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEDkr4sp31mVm7/wD/1CXpB+bYtLj
1BlRxXiyq9SthGqEetfEfg2l+9wSsTZo6iUS0tikh/XAW6foKaNz1Mtpxbq8kZop
9p8WpDkjhsYMDCRWKTqR5Tnwczu/EGZZp82HYqHDM1Bcgn3I5FhJ9ShYZZLJP8kM
mTuZIVxILJEpdzXQ9yctSShbBKdS103RnQHYBE2y7N4BBAC8lQFu/ru0hNvnNpeM
kkxZhgNVSaIfR7My5zznCwaVQzud6ZH2zcQUmfina12vRNqA7TBaQyc/Ebsdz/Pk
MCCXPDyaUgp1EJKdVd5nUnO/6yEinf1zkI5kpYd/dKSMcbMIOdEUeBsOUR7Yg6uP
oNK40Dwmg3vH5rsSEcrupzWeHwARAQABAAP6Aptku64V1jcH+zhL/AuBtrMdlK5B
6YDKP2fm9aK3YpTdXB+AfxL1JPvD7jyTvPqMsr+UrYrEHiEWnyDi1EK+EJMSnaUb
hHRFBtqapnzhJ2qXLcM8PHV5aby7dMhpMXSvF+gJEtsdSPuX2Gcuc/iNXwdymacJ
M1SY89MUbmNqvQECAMsmTUb9CvHed7xPoHAHZuAIhnvNaVosLsfnO+v78zh+8P8X
mjsT11u1ayW3wbfsY8EGOx82RnZ7hEWcCPvBk98CAO2kgj4mZ1rA08LzoAYgibdK
PaQqeZ+IS91J7+7zzB580xiKUg/HVBjHzbZvPYUPI6mX8JShhFI3heB0jq8XPcEC
AM3HHAlOqxtrjk3Cpvrcg/LPP2CSJ/rSY9Sj9izUfuZLGjJGRVogjpp5YFPJWieE
CA5Lkzv2+Hb2KQRjpmmLEqigdYifBBgBAgAJBQJNsuzeAhsMAAoJEDkr4sp31mVm
SeID/iiPXvX46QlS11QN5h+OffpFsDTjFq0yJpNAlxRiEv7Ju3Dg7syyTUt9prsW
h4rGyA1XCv72nN8JLGtA44IiEGtPMiONBe1fcuhbEvz8bzzvB4vQFwI1JPSO0Vrt
xNpaCB4GHkwcF8ii5lq+WVX6V+iryGuGNzE0ZxNMevsKHk/d
=KmYO
-----END PGP PRIVATE KEY BLOCK-----
RUBY
key3_public = <<-RUBY
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
mI0ETbLs+QEEALBpfCzDVNDWw2jWBpmNAScCmdX92voNSp+Jd0GFhabDbmfasAwO
rEKAn/PgQCOdHNT8m7EHUCTDOB2vBe360IE8+q9OylF10I6PSMvyoXHnwL/UQ4BO
dcgYYE54AmensPWlYxLlLu34gnKgSEnNULee9x4KnVfeidNj1gpQTenlABEBAAG0
IVRlc3QgbnVtYmVyIDMgPHRlc3QzQGV4YW1wbGUuY29tPoi4BBMBAgAiBQJNsuz5
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRA0d6XcPemRge3TA/9jNcgZ
ad7j6R7yUL2lYw5jeSuyiIiRzwxb8PzEOzEAUBaLBWGsLunwDjU6ZTSckNUxjmf9
sHkeAb1WmYSidsHpLaljLp/dtsYgUQg6wUNjv3VEyeT9oViEVxr6RIYyd6kTQAUK
kHjiaRXftqcgDfhgI/+Nzd8gYZxGeMudnsavcLiNBE2y7PkBBACwoV1uFEtxoufH
KMqBWMdCY8B/0D4ytgjjXBqwRN1k6QFEqUe/A+Nf8ZVE8lNyb8BHwMVoS4auOKLs
g4JeIlwvEeFAlsdABlUtkEKJEcxns3nxmCw8koiWkk9KDY9rk3ZU0UweLDFshYq/
1z/+QueKdx6uJZAHKM3DoBqpEqomhwARAQABiJ8EGAECAAkFAk2y7PkCGwwACgkQ
NHel3D3pkYFGagP/YvAIsOb5ve9441FXwlkjiGCiUugfC/8Mw7U+ufGjbDkjSgOH
+WE+Rx+iUMT55JoQX8G/bephtYq0YSa1kyKOebOc08ZBPWH/4sK/UFjnVBdCuglj
tsU3JEa9ma0EN5Iwj8cHpvzATsxS5zCIEfDYHIHNhGhnpFp4GKgN6cXD2QY=
=T5Nu
-----END PGP PUBLIC KEY BLOCK-----
RUBY
key3_secret = <<-RUBY
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
lQHXBE2y7PkBBACwaXwsw1TQ1sNo1gaZjQEnApnV/dr6DUqfiXdBhYWmw25n2rAM
DqxCgJ/z4EAjnRzU/JuxB1AkwzgdrwXt+tCBPPqvTspRddCOj0jL8qFx58C/1EOA
TnXIGGBOeAJnp7D1pWMS5S7t+IJyoEhJzVC3nvceCp1X3onTY9YKUE3p5QARAQAB
AAP4+Ayv6LVxlrhj8HtdyG+Ja2YX/GYaxR161dxPyZ0h4cVLDec1QhwCe/Q9Mrad
DG7I0+DhX4CCIpPZD+PwmzjIuIrw+CeCVFyYwnKzbjSQMCHbQaiZhCmiqItoe/P/
mf3rTX7hh6H02VtRhMcSPfFv7ckWiHz3Zc5PEUvS5E+B4QIA0b6ddoIyeEdvlrmj
IZs2gMvpj5p7ksuRX+Wo04Dw2v5qoYFamgq+junLwjo2hKP2WzE6ocAYiFycE8/i
NzG5xQIA11EKhP8nuAbLzkbz45m3o858MgugBB062rg1dcjXEd9b8CqhdLI8btPG
Nxav7bRD1HG5wEaZrHidyIohjwoRoQIAnuFG4PG878SbY+Gj3Qu9qme7k6D046Yc
quNSOeSfdqpYq5OEc3EtPkYonEgA9yBWzDHlLCz4+QOsGl0vBaltCawItCFUZXN0
IG51bWJlciAzIDx0ZXN0M0BleGFtcGxlLmNvbT6IuAQTAQIAIgUCTbLs+QIbAwYL
CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQNHel3D3pkYHt0wP/YzXIGWne4+ke
8lC9pWMOY3krsoiIkc8MW/D8xDsxAFAWiwVhrC7p8A41OmU0nJDVMY5n/bB5HgG9
VpmEonbB6S2pYy6f3bbGIFEIOsFDY791RMnk/aFYhFca+kSGMnepE0AFCpB44mkV
37anIA34YCP/jc3fIGGcRnjLnZ7Gr3CdAdgETbLs+QEEALChXW4US3Gi58coyoFY
x0JjwH/QPjK2CONcGrBE3WTpAUSpR78D41/xlUTyU3JvwEfAxWhLhq44ouyDgl4i
XC8R4UCWx0AGVS2QQokRzGezefGYLDySiJaST0oNj2uTdlTRTB4sMWyFir/XP/5C
54p3Hq4lkAcozcOgGqkSqiaHABEBAAEAA/wLlyMm4I0M0WhNMNeNAlLc/+e3W2Zh
dIGDzdzweSxf/Uw4gbU0CyDGAHfPlOk15rBi5PrvO5mEYDIMvBp3a+DJmAUSZJFl
aFIOIemhYYildvoIDisBtkdR35+/5WBCYRRgawo1jPo8v3icK++FWjJe6R5Y4GTD
1WEltWM8S0x/aQIA0VzMSeSt4gRpjafjnyUATMGa8eYAgydOHiwkqIsMnm0m1Zua
P/VBvkFxUKs/62GWr0USrn6TShdTChDu4Q1aXwIA1/n3utDkfGOrKL7w3CplMP8O
SAmzqh79VSzoT7oBW+oqapy/JFpN+hJ5FeIVPWCP8/HlHdtq32X7hbNuQ4r02QIA
ytqWvM//YeZcoUfckrxumMpEW613YYMCbIDW51EauKFrAxK1hqHl1I8VwXs8H+6v
JvDNxSddjC/bMZ/QivwJyaDfiJ8EGAECAAkFAk2y7PkCGwwACgkQNHel3D3pkYFG
agP/YvAIsOb5ve9441FXwlkjiGCiUugfC/8Mw7U+ufGjbDkjSgOH+WE+Rx+iUMT5
5JoQX8G/bephtYq0YSa1kyKOebOc08ZBPWH/4sK/UFjnVBdCugljtsU3JEa9ma0E
N5Iwj8cHpvzATsxS5zCIEfDYHIHNhGhnpFp4GKgN6cXD2QY=
=QWZy
-----END PGP PRIVATE KEY BLOCK-----
RUBY
key4_public = <<-RUBY
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
mI0ETbLtDQEEAKBGC+ZlPZitUGQ76XxF8xm3qCAwm30xitHq4jAItbQ6GfsVZb1r
jKjOcupf2LPDrnhCZ5eTXvFCc4mqvv3fJAeoAD6nEIQmG7DYeYoGwVztFTRajLFG
krgchcYpopi5Xq5IUe57UaFMt6SEqzajAJWSD6303rHIJJ/2SaQA0wEZABEBAAG0
IVRlc3QgbnVtYmVyIDQgPHRlc3Q0QGV4YW1wbGUuY29tPoi4BBMBAgAiBQJNsu0N
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAKfJF4Vk6CPfZcA/0b7FZE
zvsNdxESao+UO0ReXIVKT3vl+7NdauiSsQQsg0/zxxXxctmAq6oalHg1pbQLWxgI
uKPH1sxgSOZ1LGWEPENRwi9oVv6ENJVKcX87OUdCPu3gryr6os0oSSpXzYTEFBgJ
RNJdqL7+Y73P9glMhzDb1eZM0TFHI2nr2fzfe7iNBE2y7Q0BBADY38LZ3YAIgq3r
k54Y6x3mN5TyMTex994jC91UCYqHFwhIM2v0UlsA/QkqbS8nbqOH2zDzEFs29Wcv
cUeHWBQaAtiHr/izNy4Qo9pXW3eI5vDfeXEB0MGk21JqabPLWTd5zcNlXXfr6TxK
0+h9Ivbk0mPSP/E3XcUrJtJyml6ilQARAQABiJ8EGAECAAkFAk2y7Q0CGwwACgkQ
CnyReFZOgj1NWwP9FKrmuEN+RfsPsVHEv0liGFyKbcyteB+12Zp+aNzMddCOLYXA
jvoMv2F+WfrAvzdwUeYWq93An6w44TV7GfsVky8IDHXZ4wAnUrE2tuCvCPqUToVV
OBjCYD0To97vULkS/+bU1+jAE3IYtedYNFdGhd0cm4kLzFVlAzc9xDLTp08=
=Emj0
-----END PGP PUBLIC KEY BLOCK-----
RUBY
key4_secret = <<-RUBY
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
lQHYBE2y7Q0BBACgRgvmZT2YrVBkO+l8RfMZt6ggMJt9MYrR6uIwCLW0Ohn7FWW9
a4yoznLqX9izw654QmeXk17xQnOJqr793yQHqAA+pxCEJhuw2HmKBsFc7RU0Woyx
RpK4HIXGKaKYuV6uSFHue1GhTLekhKs2owCVkg+t9N6xyCSf9kmkANMBGQARAQAB
AAP9EKVFvh98prs1UruwM7J2HZEn+nPh6j43ezbIWBHHgVjZcuzVfLdLTAro/3OF
56GmoKHQ7XqmTStIIZ+kp2xB6wmQnQ8bxjOwWZ40/hH/r57Ednz5nflJQeknXvlV
j6sxJKJppyfu5bk9ouwV/ImOOicOwjBWT6ZxiA8BNhWN0JMCAMdLskpD1OYaNHcg
Vlt1IXNEG4yUpdPjtlCoCNd4fy+BCvBkXQ44dtsV6XH0E3Z2DX/gantvioui315f
2Iez9CcCAM3gD0dGAZ6m9pOcjYqMNFAL6TqV+cY/LonBCZar+IZ4E2dWdn5Nqj3A
pBWYl7ENziYL7/4uvqYrHXQw/UKgaL8B/0weNCbxJEelVihv6ULpAfisLE7a/qlI
5hu3jnTwoVzZFPLUO7/UYuZFlF6R2mzrVzxzCvsax7phAoV18CEPiuKg27QhVGVz
dCBudW1iZXIgNCA8dGVzdDRAZXhhbXBsZS5jb20+iLgEEwECACIFAk2y7Q0CGwMG
CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEAp8kXhWToI99lwD/RvsVkTO+w13
ERJqj5Q7RF5chUpPe+X7s11q6JKxBCyDT/PHFfFy2YCrqhqUeDWltAtbGAi4o8fW
zGBI5nUsZYQ8Q1HCL2hW/oQ0lUpxfzs5R0I+7eCvKvqizShJKlfNhMQUGAlE0l2o
vv5jvc/2CUyHMNvV5kzRMUcjaevZ/N97nQHYBE2y7Q0BBADY38LZ3YAIgq3rk54Y
6x3mN5TyMTex994jC91UCYqHFwhIM2v0UlsA/QkqbS8nbqOH2zDzEFs29WcvcUeH
WBQaAtiHr/izNy4Qo9pXW3eI5vDfeXEB0MGk21JqabPLWTd5zcNlXXfr6TxK0+h9
Ivbk0mPSP/E3XcUrJtJyml6ilQARAQABAAP6Amin1s4k7iiaFcKtD/H1QiRDZquW
cVxYrrMiyUcVhLnELohzA5gc6SZRAVQ29h0+j+jRbXMKJFKLoRqvv0iCk/XOtEFO
keuBQwE3depOiy7lHl6LYd4q3tbu23dKEGnpa8bvQujEJa/uzt9WX90IS80pUGkf
EUjquOZrCLTc0skCAN87u9Ezy9x9z55KtiCjoMCCod98elSX9mG+tbfOAmRsmBkV
RU0Bzvz/465EQPcv3EthgBaH1ri3dnP1KUorOl0CAPi1Efg1+tE7SOm7MVt9maC9
zh4LAnD4tNhYr93CmnQw85NQmggtRW0/qnk6MF0TM/nS9tVWIFINcqYrDb0JtZkC
AOWgGo5NFrrYnSpE2afTkuQZjKzxED98MmgjCKdEV4eRE8j8IWGsgD+l4kp/+fL+
wPMzfTjcV/XVdhEMPTPPFE6hmIifBBgBAgAJBQJNsu0NAhsMAAoJEAp8kXhWToI9
TVsD/RSq5rhDfkX7D7FRxL9JYhhcim3MrXgftdmafmjczHXQji2FwI76DL9hfln6
wL83cFHmFqvdwJ+sOOE1exn7FZMvCAx12eMAJ1KxNrbgrwj6lE6FVTgYwmA9E6Pe
71C5Ev/m1NfowBNyGLXnWDRXRoXdHJuJC8xVZQM3PcQy06dP
=SMnt
-----END PGP PRIVATE KEY BLOCK-----
RUBY
password_key_public = <<-RUBY
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
mQENBE20i3MBCACuRmguvjHCkZaJGu9mD/vMa4ytavXYLqQ0HBQe6RAqVarAidFf
bKfIAuaqg9xRpnNpDL+hPqbOiYcxy6USw0hvEhLUem83KHIwU8t6+Fu5vRYOxgch
R/t66N9+B5TfxXg5fAKl7dKesXXw1VwS6jnmjWB1NaWwfmhRkbSQbCRKW38JNQ6t
xysZnFDtqmp1Y/vb4LZ8Q87ITfHkxLAfPKEFh25qMfXB/iXgP4NnFOFH1bZ9sz4E
cX0sXEAXKtrpHFOg78qTQaucKu7fBJo+r/crAK7SWutGCv5R5kE+sLNWsOdgFz4k
CdwgxQeK0URwMF9kNHb/HHwfiWUZZrkAu0sxABEBAAG0M1Rlc3Qgd2l0aCBwYXNz
d29yZCA8dGVzdF93aXRoX3Bhc3N3b3JkQGV4YW1wbGUuY29tPokBOAQTAQIAIgUC
TbSLcwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ8QmEM7hLckmStQf+
JYFRx82ufCAZ4PjcXJJJsb1M4jhUo9/mOdWaQy19E5n6OM1heG5dWgoPTBL8t96G
XQmum9zD2bI6hOIT/0z85Sm/+tbQwZUUba9Rw8/NHnjOuvVxr6DHQOtC86LezIY0
zrVk6sfCDw0Ll/i3q8zjY5oZw7VOOhCwPd6vhWtdPfW5QQ8/gC/gAGZiHm6Cf1nf
JV+WRtyUKNnlDVa9iPe4CdTGQfqqgpMWEoHV6NKfQ69A2dNA1SRX2XEecoEXwcnq
HVO9NqZDdr3NFfMmDEo7vAD77d7hXEFE4MBR5E2C91P+sOuOTVDjVQ3tucJ7qesw
puyJCPsWWsd9omxTze+RYrkBDQRNtItzAQgAlHfZpWMwcmi1YpGDFdALSk4pozBV
jjc9QsrWGozmJUpI1SAXOto3k3apR4lPzBsUOuf3bAt2A2e0CWPpCUWPByzm/Hpg
nIOPAK6Ab9hGpSGSObegz6mNUbhDopmh0XojejWm3CExtBadIY8ukSKOZSqnWsO0
MQ08eW5xMApqeajtTY8U2U4tVT3BGw0XM5Tqrtg05e0GmYa3wGssjI6f7A1i0InB
oAxy3AYL2jVPkODsPiUwK6DIfpsc+FQk4ouWfZcp3sgOJXhcoOaL6/Xpb/Rzpy+G
HaO9+xU/btkcx6IQV0icygFNxcQUDbBBESjDVoRvDbAtWg0rXkeK9N5bAQARAQAB
iQEfBBgBAgAJBQJNtItzAhsMAAoJEPEJhDO4S3JJS7EH/Rl8NOMaLFs7wpghmoqo
PHQhzkcV8zXJ8gwT+2qAz1Et9oyU1pHBT/1E+8XqrMlXQhcCevhmwlQdIIQpfzXZ
eserXabPKrwPDkwPoajVFLVc1WPHzBbmuBP/7XSgEXxfKXE8qA3nAkiidnfdA7ww
WB+4iMYnsimKAQxTLQvwZE3twnt+5hPbtg89BSaYSv2WuBkh/qAb8DxoffjenTko
RPX4fQDveZa4UswstJNM1s1hq/idQtCzgrRw0/ZD2g/hupBbXlM7dm+Iiuy+hMFM
G4bNiySxInxh/nfvsvlz9xgePjqxptjVggEVVkKHvkb8Z+MX+/N632WOVkIw2HFB
tck=
=hRl0
-----END PGP PUBLIC KEY BLOCK-----
RUBY
password_key_secret = <<-RUBY
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
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
=9u2Q
-----END PGP PRIVATE KEY BLOCK-----
RUBY
expired_key_public = <<-RUBY
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
mI0ETb8S8gEEAK2m1FMu8mAWS+WwnQIXLikRegUC5faHFpNNwqp9SgH4GuWxq2iQ
PfnSHRhE6qtcK6DVqJv4R6h1AfCCd1Vdgp8FtWyCA6dgxflH206VY+GgfwbK6nDs
eiCX9wFNKZjXrmesOete1oxIrqDKpNQbJ1zwGSQ+GW3KQFq4gImTiA17ABEBAAG0
JkV4cGlyZWQgS2V5IDx0ZXN0X2V4cGlyZWRAZXhhbXBsZS5jb20+iL4EEwECACgF
Ak2/EvICGwMFCQABUYAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEDY/0HHE
tnipp88D/RSAytabxU9uGCba4mEla/6PJavnqA1y+Pfuvqq6mlAOPTsL/Y5TXyp7
USEgqmigdga+FHVJfZu3C+uxkIkzGjhi4iuL7nI3gGwGNd82HJL0j1WnM47brPjo
F85SxAyn0LXk77piMVlK96TfQFX0Zk+Zz8QEaW3B59O705US6Q8puI0ETb8S8gEE
ANBET93bCi3SalKuNtT5D7L7+zNgiP9xEpCIhoUbW0OVJ3Nz1iSWRLYeQsPyKnhZ
Ws1Gv9Bp7MC5iOP1jtPd81elrwN71o+4xT7nv3Hvz1JzuhrYFC/wKcz1DG/Diset
jKPJu/W8ip0K5jYvDIUrDO8g9jCc8m80wMhxMzpsVNhnABEBAAGIpQQYAQIADwUC
Tb8S8gIbDAUJAAFRgAAKCRA2P9BxxLZ4qbMOA/9XY586CtP1QCVvIdlJVVuLc/mu
I7IVAp03q4hqA6ykooLFu3FzYFTCENcyvemEB4TJhfG6XYmrq5N0jOrl6BB/ONLc
37OBnsxWQBKVbn7yzDb6WzsMtAlQ8Q8S5oYbIWSt+nUoE5slZ+tx9ngzLG20IpUH
sunYPhvnuBAfIRuA0A==
=tKG5
-----END PGP PUBLIC KEY BLOCK-----
RUBY
expired_key_secret = <<-RUBY
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.11 (Darwin)
lQHYBE2/EvIBBACtptRTLvJgFkvlsJ0CFy4pEXoFAuX2hxaTTcKqfUoB+Brlsato
kD350h0YROqrXCug1aib+EeodQHwgndVXYKfBbVsggOnYMX5R9tOlWPhoH8Gyupw
7Hogl/cBTSmY165nrDnrXtaMSK6gyqTUGydc8BkkPhltykBauICJk4gNewARAQAB
AAP8DWaEl6kiZRqmkrwO8bYn05CyS0HoMx6rnFE+ed+fRW86/1ZQzvBKoaux0q/T
mC1NsWSriHwfzR0loCsnprvHmsaX7O7W4PHZRN+xB9clpRGfEnHiyljWuaP8bxWg
r57fmnJ+bFoWanyxZsHoYZrVOlMa6JpQiQ+y0QUsbykTCPECAMt6Z3qc54JtU3Rt
lNzHNE7zRYt1z2fRGnOmrh0ch5TF9x+uRqQ/Am4VYe6Xzjhj6HBO7tB/n4xK4ypz
JLviw8MCANp5hw99W1AOTXpIkIS7xC9Pbx2j8AwAW5nlzyFILX+mQR/SmUX1H722
A8gj98hb6UUuf+CRzx7/FB6gk6Yzi+kCAMhcDPRgDUPggcOSdCdZDbZ78xwHwwOS
+9MT+VkIYDmOJOSer9xUdtGPcr8t/kGeICFSqZC2My38Sj1TJTs4rn2gtrQmRXhw
aXJlZCBLZXkgPHRlc3RfZXhwaXJlZEBleGFtcGxlLmNvbT6IvgQTAQIAKAUCTb8S
8gIbAwUJAAFRgAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQNj/QccS2eKmn
zwP9FIDK1pvFT24YJtriYSVr/o8lq+eoDXL49+6+qrqaUA49Owv9jlNfKntRISCq
aKB2Br4UdUl9m7cL67GQiTMaOGLiK4vucjeAbAY13zYckvSPVaczjtus+OgXzlLE
DKfQteTvumIxWUr3pN9AVfRmT5nPxARpbcHn07vTlRLpDymdAdgETb8S8gEEANBE
T93bCi3SalKuNtT5D7L7+zNgiP9xEpCIhoUbW0OVJ3Nz1iSWRLYeQsPyKnhZWs1G
v9Bp7MC5iOP1jtPd81elrwN71o+4xT7nv3Hvz1JzuhrYFC/wKcz1DG/DisetjKPJ
u/W8ip0K5jYvDIUrDO8g9jCc8m80wMhxMzpsVNhnABEBAAEAA/0VV0Kl1amb22lY
spBcz26r5QUvFQ/EuRXxaIP8RLrb2H9T5cVGN32v+bbWtExky6cxzLOgDBKeBwT/
cuyhSieCntuxgjHoRRO8CKDSAWsjRTC/R9UpnTk+UiCrxK/2Bk7BorFbBR+lcmi9
bddoOe6p/LAFvJhK7y6OCCUqrh08LQIA4pPdh/8HdDgaHLaBkFMq3L5HVD1WfyVf
emCNIfGmE5i9JU0VRU7xPJXlEWxKmFPKdlGOAT8V4QSgLVvp7H+3OwIA60+9rWrB
i3mQgjETNM2mT0wDrXNCyuR2MdeOfCyEYY+4xBLdPs7aSsVakQrx/1B8WZkWZUNU
d7iuHlKaickIxQIA50UW9VuaMxyImLIdt2RzcLacOC98oMvZ8R/5ShkWunGOkUka
0YHOGCUAqhjwh5SFKjp3VYfy22P3YR1Usj8ETpmRiKUEGAECAA8FAk2/EvICGwwF
CQABUYAACgkQNj/QccS2eKmzDgP/V2OfOgrT9UAlbyHZSVVbi3P5riOyFQKdN6uI
agOspKKCxbtxc2BUwhDXMr3phAeEyYXxul2Jq6uTdIzq5egQfzjS3N+zgZ7MVkAS
lW5+8sw2+ls7DLQJUPEPEuaGGyFkrfp1KBObJWfrcfZ4MyxttCKVB7Lp2D4b57gQ
HyEbgNA=
=NliS
-----END PGP PRIVATE KEY BLOCK-----
RUBY
encrypted_text = <<-RUBY
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.11 (Darwin)
hIwDbJ4P+uQnvtQBA/9OXytdl9XAnzDZau1nTDkqpYKUp4ZoBvwASwxexj4VWX8i
jo1AuJi7pzSrBssjDsMAXcnfzHsEKh6g3xu15Gttn1oR7oB8/Q8AlC8nX8Wwsg+n
EpS/TNE/oPae8EbPCNAYuWHaGOzkH1LNQ4fpYy1q2t6+Er3uyzq0LhXTJZTM3oSM
A2c0CKWdjRgiAQQAkRQ0VPk7emnx/1FeUIlOaGgQa4KnNUw/FIZYdQNh/FJm2oTp
wunScJXvxVTZjk4eE6QAcuBH/lV1mrRF37o+7XMDuzafhT+qxqoUF8SUkCw79jrm
NBaDYWiFPkECUMcAQOL9Uk3DvJ2vxpGMJ2g0wEcrcEEikY6juSAaZX+1TwCEjAOk
LkSJkASuIQED/jza/ZOZvk6GNpDeAJbsFWc0QGlkQ0wKiPer9PUQAuNMXFnaAbvx
t9dB9AtLnnFPM8Cpg8DqLdGuWkaa5gvdjW7weLSYRo7LCYQ3ZOHUUeavAN1RLKel
IiaofRm6Bm2JDgIv1Hz0Yfj5hGylGKDT7PqA7+jXYnymjugBLVoXfP4ahIwDwk/m
ZyOifKABBACEbNa0tv5XHyzyvm/kB6AU+Lz3Ixwcp7KC6k1KE5ZYwoVg51VIOu+S
EQxQzMJrL7QfL5H1Aq4aFWHgr6I+k9sqeFr4TIAx6/H53//VIAP4+zOeGMldRwNY
AG4qd+AxLNBEr/8HoGS8h+46Vudj4ykqmOQCX4sKRaiWcUkwzdUMtNJGAeAhDfVQ
n/W/yDGzkeGlzC7Wr5Fi83c5FD+J/eSsZo+dKTlKK/zEtvKhZKvoY5gHiS20KlI0
TWl5uBcWluXyqRqnCV5uLA==
=Tsce
-----END PGP MESSAGE-----
RUBY
signed_text = <<-RUBY
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.11 (Darwin)
hIwDbJ4P+uQnvtQBA/sEXKjykfQvuvJdvdtc105JrjyXYmbRRbvRxI+1axeqttSd
6osDKwjBYYtYR9S3gdR0VjugFzHKP3XnbkPkeASbY4J7C3Tr0UlyZd0+0ZdIRFLa
mO9HxOjDZz3h3Sn1cl/D8JtH7KVYhbKYAEXTybUInu6jcWiXDgIQVZYpLgS0wISM
A2c0CKWdjRgiAQP+IZ93Yj+6Jqggr7NYOV+hBWAWj6NAIxx0zh1QSyPWPqBAQbQj
KlRljCX85rXHWXU2JW/BdQxBoF1ANuE3+HwZoDbwtOKFhRTuBKUN/YpphluUMmJ/
W0Wq6QL8v4+awwQX7eLE0T3FxQko57kLw//XqYsuv2RVCOYVbfQUmKHo0z2EjAOk
LkSJkASuIQED/iz3m6dONzuxuMesy6AY7gxa+Okgb7H2Is2ARGy1riNaLNhf5WZN
tsDd6QBod1i/tSwsMrbBjePPSyCyjD17QjdpieXtAqWfqwhxq0/KJtLmCwctHPnJ
1fhPp8oy+n/et0UyQgiH/yI3bxVT/39ZURIf1QstD/HGPnI5upnIn4S2hIwDwk/m
ZyOifKABA/4qTB94c2bVir7Pg1uvO6cvQwb2Pj8UUAFysZt7WHVTcvpm33lj5wkP
QyY7o2rMKSS8qAmmBWOsfAPF5gCvgp4D2Kr5FB5kYWzmFOFxuIN8ayz25BJ+4YGQ
GdWwjSPU69/eet6q7p+XydGY8jv4e6u/2tAi3b2O5Kt0th1rftOJENLAMgFgGMNE
M2S5q+RE1apf28qfqbMzSQ2Nccx+kaIkGDjieYIBhG2f3Yuh8GBdQHpyaNH0x/eY
XnHuRow0gy1jagiIDGK96N4tBOOhacR+Nf15gYMyvfZUszgwudiZP8uwUluA1w/v
+yjqnb2CVGx0iW7Yv71dxdojx7vpJ+WePHe+zJMHb260tAOmBDhjDjJ4eDqcP6Yk
d8NEvpzk2zUiB6Hb6SXPBYp+0cUQG5sYCEZQLunQJ1CeXzAfRxoyv5k7gYG/wZ5L
jVRh9AFdOceUv5zZJpiSYXYXyntWqSy4Q5zguQmzhE5Wu3mY9HYPcpAUHxbn
=rt/Y
-----END PGP MESSAGE-----
RUBY
signed_with_expired_key_text = <<-RUBY
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.11 (Darwin)
owGbwMvMwMRoZn+h8Mi2ipWMpwWTmHXVzH33C7d6ZCqUZKQWpXbMYWFgZGJgY2UC
iTJwcQrAVDsoMv9mvx954X+W9uzfGSVVvlE5n3yFrdn2CB/q0jr4Um5C/Notby0t
YxibhPfqpC4Sy3UMfHd/76qvBp8cZv3749/xJ2LZGT9O39nsM7yvfXsjttm1Kyv1
unDJJQnpxHlOubtKPuTkLU+aZOQtf1/zsRKTz5zv37XLTY6qWdy18fr0t1fbf8o9
jxAA
=Vta9
-----END PGP MESSAGE-----
RUBY
unavailable = <<-RUBY
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.11 (Darwin)
hIwDlCBoTwSpYjABA/9pn3d5xYasfQYquQzLwI0ASVuvuofjJZrYyKEYLEPHPaFn
SJOMJRFJh4lC6UfGs7xktX0bONwsdGo0EaIP6H5W+WFW0W2VCxyqLLorCWa/XFi8
Nr/2iVyj5s3QSfXGXDmnlRCf9PiAiBPPy2DzYgD3KLXMZH2hAxUtJmouuIgVWdJG
AYKArJ8pJFbrtrIiPuNIjj0yhiNGx65GIfnF32fulpgzLbyWymlpkrzRRO6sz2wl
EEdpZ6VKsLuoOb9Ou+hD6CLC3Izzmw==
=bsMi
-----END PGP MESSAGE-----
RUBY
sign = <<-RUBY
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.11 (Darwin)
owGbwMvMwCQo65qZfvagZjzjacEkZl01c98VK/96ZCqUZKQWpXa4sTAIMjGwsTKB
RBm4OAVgqt3PMSxYZXVcSzq4uZvry7RCp9vN31o+LTnBML+wgKFg6aJPKysdX2fc
+rtEd/85jh4A
=aECe
-----END PGP MESSAGE-----
RUBY
passwored = <<-RUBY
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.11 (Darwin)
hQEMAykL9/bExDNQAQf/ZXL4iUQEzoE0XfBLakpLTV5euOvdGFVPxrFS481i/Ldi
Yfpoo/gbB0yEwKnm0faCRSz2AiOQ4f3iIWRwdwoEYTbCW/o1/iXKH8fp6GXd4hQG
JdRIwr7GoGQFuOb96kZL3TbO4VapC6ubx5evxyhCIRLZPL415YXdGAcqnVvYew92
pzZn0RWe2dXDlE1HTENVvHoABnBgOOLSE/37kJJYWgsk1QJCSbaxsS6sZdJXcINQ
uqeKQKagF15DVYRA27viX0IZ9J2x9ytPQWLdf0wc8dE0h4NJiEwL6myU2WPR27xx
Lrrp3kD2wewwUSljOW/SbXS6TNLSEiLILUZkTr5+F9JIAWF1YLZTxjN9HxABuboy
wYhnVMaM+gQKDMgbIXdxim0ssq2ICHROYkbC/JTEIVXqnJbKLivfNP6J0ROHcczO
w/3/C0MallvG
=hrCw
-----END PGP MESSAGE-----
RUBY
KEYS = []
KEYS << { :sha => 'test1@example.com', :public => key1_public, :secret => key1_secret}
KEYS << { :sha => 'test2@example.com', :public => key2_public, :secret => key2_secret}
KEYS << { :sha => 'test3@example.com', :public => key3_public, :secret => key3_secret}
KEYS << { :sha => 'test4@example.com', :public => key4_public, :secret => key4_secret}
PLAIN_KEY = { :sha => 'test1@example.com', :public => key1_public, :secret => key1_secret }
PASSWORD_KEY = {
:sha => 'test_with_password@example.com',
:public => password_key_public,
:secret => password_key_secret
}
EXPIRED_KEY = {
:sha => "test_expired@example.com",
:public => expired_key_public,
:secret => expired_key_secret
}
TEXT = {
:plain => "Hi there",
:encrypted => encrypted_text.chomp,
# Created with a temporary key that's been removed.
:unavailable => unavailable.chomp,
:signed => signed_text.chomp,
:sign => sign.chomp,
:passwored => passwored.chomp,
:expired_key_sign => signed_with_expired_key_text.chomp
}
KEY_1_ENCRYPTED = <<-RUBY
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
hIwDbJ4P+uQnvtQBBACOzUqiKHRS8cEDPpQl1dQznpxcWW3Md8X3eFRx3+qD0X7+
aEadz/cUXf7nO9KimeO7qhqNBJoPQEzZTqirebLgq2pq+Rtp2zGCvU1hUnAmVm27
CZE/quNaBV33V0haddWm4Y8AD7e7T2a2LBDrMNGsD9eKjREJ+g/Pmm5WLRDx69JP
AaXe0Msjfyapj07hCPZptE8iP2/tCSvRDmiSgidPAZM4NnL2ANwfT6kslVha0mos
MH+qcPlxAMrMnjuWs+wFiVnWLEYfIqNzH7Z2irC2NA==
=O59i
-----END PGP MESSAGE-----
RUBY
gpgme-2.0.16/test/sub_key_test.rb 0000644 0000041 0000041 00000002251 13234766064 016746 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'test_helper'
describe GPGME::SubKey do
before do
skip unless ensure_keys GPGME::PROTOCOL_OpenPGP
end
# We trust Key for common methods that come from KeyCommon
it "has certain attributes" do
subkey = GPGME::Key.find(:secret).first.primary_subkey
[:pubkey_algo, :length, :keyid, :fpr, :fingerprint].each do |attrib|
assert subkey.respond_to?(attrib), "Key doesn't respond to #{attrib}"
end
end
it "won't allow the creation of GPGME::SubKey's without the C API" do
assert_raises NoMethodError do
GPGME::SubKey.new
end
end
it "knows if the key is expired" do
subkey = GPGME::Key.find(:secret).first.primary_subkey
refute subkey.expired
with_key EXPIRED_KEY do
subkey = GPGME::Key.find(:secret, EXPIRED_KEY[:sha]).first.primary_subkey
assert subkey.expired
end
end
describe :inspect do
it "can be inspected" do
subkey = GPGME::Key.find(:secret).first.primary_subkey
subkey.inspect
end
end
describe :to_s do
it "can be coerced into a String" do
subkey = GPGME::Key.find(:secret).first.primary_subkey
subkey.to_s
end
end
end
gpgme-2.0.16/test/data_test.rb 0000644 0000041 0000041 00000007404 13234766064 016223 0 ustar www-data www-data # -*- encoding: utf-8 -*-
require 'test_helper'
describe GPGME::Data do
describe :new do
it "smartly creates an empty buffer if nothing passed" do
data = GPGME::Data.new
assert_instance_of GPGME::Data, data
assert_respond_to data, :read
assert_respond_to data, :write
end
it "doesn't create a new object if the object passed is a Data already" do
data = GPGME::Data.new
new_data = GPGME::Data.new(data)
assert_equal data, new_data
end
it "creates a data from strings" do
data = GPGME::Data.new("wadus")
assert_equal "wadus", data.read
end
it "creates a data from a file" do
# magic fromfile
data = GPGME::Data.new(File.open(__FILE__))
assert_match /magic fromfile/, data.read
end
it "creates a data from file descriptor" do
# magic filedescriptor
File.open(__FILE__) do |f|
data = GPGME::Data.new(f.fileno)
assert_match /magic filedescriptor/, data.read
end
end
end
describe :read do
it "allows to read only a length of the object" do
data = GPGME::Data.new("wadus")
assert_equal "wad", data.read(3)
end
it "returns nil if reading 0 length" do
data = GPGME::Data.new("wadus")
assert_nil data.read(0)
end
it "returns the full thing if reading without parameter" do
data = GPGME::Data.new("wadus")
assert_equal "wadus", data.read
end
end
##
# We consider seek tested by these ones, since we have to seek(0) before
# reading.
describe :write do
it "writes data to it" do
data = GPGME::Data.new
data.write("wadus")
data.seek(0)
assert_equal "wadus", data.read
end
it "writes data to it, specifying the length of the things to write" do
data = GPGME::Data.new
data.write("wadus", 5)
data.seek(0)
assert_equal "wadus", data.read
end
it "writes only a limited part if specified a small number" do
data = GPGME::Data.new
data.write("wadus", 3)
data.seek(0)
assert_equal "wad", data.read
end
# TODO: test doesn't pass, I believe there might be a security issue here,
# random crap is written to the buffer if a longer size is passed.
#
# it "writes only the full data passed even if the length is bigger" do
# data = GPGME::Data.new
# data.write("wadus", 100)
# data.seek(0)
# assert_equal "wadus", data.read
# end
end
describe :encoding do
it "has encoding 0 by default (DATA_ENCODING_NONE)" do
data = GPGME::Data.new("wadus")
assert_equal GPGME::DATA_ENCODING_NONE, data.encoding
end
it "can set encodings" do
data = GPGME::Data.new("wadus")
[ GPGME::DATA_ENCODING_ARMOR, GPGME::DATA_ENCODING_BASE64,
GPGME::DATA_ENCODING_BINARY,GPGME::DATA_ENCODING_NONE ].each do |encoding|
data.encoding = encoding
assert_equal encoding, data.encoding
end
end
it "breaks if not set a proper encoding value" do
data = GPGME::Data.new("wadus")
assert_raises GPGME::Error::InvalidValue do
data.encoding = 64
end
end
end
describe :file_name do
it "has no name by default" do
data = GPGME::Data.new("wadus")
assert_nil data.file_name
end
it "can set file_name" do
data = GPGME::Data.new("wadus")
[ "foo.bar", nil ].each do |file_name|
data.file_name = file_name
assert_equal file_name, data.file_name
end
end
end
describe :to_s do
it "returns the entire content of data" do
data = GPGME::Data.new("wadus")
data.read
old_pos = data.seek(0, IO::SEEK_CUR)
assert_equal "wadus", data.to_s
new_pos = data.seek(0, IO::SEEK_CUR)
assert_equal old_pos, new_pos
end
end
end
gpgme-2.0.16/gpgme.gemspec 0000644 0000041 0000041 00000006125 13234766066 015414 0 ustar www-data www-data #########################################################
# This file has been automatically generated by gem2tgz #
#########################################################
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = "gpgme"
s.version = "2.0.16"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Daiki Ueno", "Albert Llop"]
s.date = "2018-01-03"
s.description = "Ruby-GPGME is a Ruby language binding of GPGME (GnuPG\nMade Easy). GnuPG Made Easy (GPGME) is a library designed to make access to\nGnuPG easier for applications. It provides a High-Level Crypto API for\nencryption, decryption, signing, signature verification and key management."
s.email = "ueno@gnu.org"
s.extensions = ["ext/gpgme/extconf.rb"]
s.files = ["examples/edit.rb", "examples/genkey.rb", "examples/keylist.rb", "examples/roundtrip.rb", "examples/sign.rb", "examples/verify.rb", "ext/gpgme/extconf.rb", "ext/gpgme/gpgme_n.c", "lib/gpgme.rb", "lib/gpgme/compat.rb", "lib/gpgme/constants.rb", "lib/gpgme/crypto.rb", "lib/gpgme/ctx.rb", "lib/gpgme/data.rb", "lib/gpgme/engine.rb", "lib/gpgme/error.rb", "lib/gpgme/io_callbacks.rb", "lib/gpgme/key.rb", "lib/gpgme/key_common.rb", "lib/gpgme/key_sig.rb", "lib/gpgme/misc.rb", "lib/gpgme/signature.rb", "lib/gpgme/sub_key.rb", "lib/gpgme/user_id.rb", "lib/gpgme/version.rb", "ports/archives/gpgme-1.9.0.tar.bz2", "ports/archives/libassuan-2.4.3.tar.bz2", "ports/archives/libgpg-error-1.27.tar.bz2", "test/crypto_test.rb", "test/ctx_test.rb", "test/data_test.rb", "test/files/testkey_pub.gpg", "test/files/testkey_sec.gpg", "test/gpgme_test.rb", "test/key_test.rb", "test/signature_test.rb", "test/sub_key_test.rb", "test/support/resources.rb", "test/test_helper.rb"]
s.homepage = "http://github.com/ueno/ruby-gpgme"
s.licenses = ["LGPL-2.1+"]
s.require_paths = ["ext", "lib"]
s.rubyforge_project = "ruby-gpgme"
s.rubygems_version = "1.8.23"
s.summary = "Ruby binding of GPGME."
if s.respond_to? :specification_version then
s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_development_dependency(%q, ["~> 3.5.1"])
s.add_development_dependency(%q, [">= 0"])
s.add_runtime_dependency(%q, ["~> 2.3"])
s.add_development_dependency(%q, ["~> 2.1.0"])
s.add_development_dependency(%q, ["~> 0.9.12"])
s.add_development_dependency(%q, ["~> 0.9.11"])
else
s.add_dependency(%q, ["~> 3.5.1"])
s.add_dependency(%q, [">= 0"])
s.add_dependency(%q, ["~> 2.3"])
s.add_dependency(%q, ["~> 2.1.0"])
s.add_dependency(%q, ["~> 0.9.12"])
s.add_dependency(%q, ["~> 0.9.11"])
end
else
s.add_dependency(%q, ["~> 3.5.1"])
s.add_dependency(%q, [">= 0"])
s.add_dependency(%q, ["~> 2.3"])
s.add_dependency(%q, ["~> 2.1.0"])
s.add_dependency(%q, ["~> 0.9.12"])
s.add_dependency(%q, ["~> 0.9.11"])
end
end
gpgme-2.0.16/ports/ 0000755 0000041 0000041 00000000000 13234766063 014110 5 ustar www-data www-data gpgme-2.0.16/ports/archives/ 0000755 0000041 0000041 00000000000 13234766064 015715 5 ustar www-data www-data gpgme-2.0.16/ports/archives/libgpg-error-1.27.tar.bz2 0000644 0000041 0000041 00003064004 13234766064 022110 0 ustar www-data www-data BZh91AY&SYÍNÝ9
Šÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ` ^ÎlR]ˆ` ! ÈcsÞúùëJ§ÓÝ—Y> ÛÝ÷Õ.µïn}pñòÝèi §ôtyûyZQG¾í‡CÝ»ÓÖR$¯±€ˆRD¥K¬ û·–öf÷zõPßgA! :$)J22¢@×@ ú·ÞǪ#gÖ»b² ÕêxT}g-±“}Ýí½÷ÝÙɧAÑ^ùÛ»Û¤«ºê»qî»[*7«ÃããÍ^Ï<ݽÎ;j:ïžÝè»}²¾µöîÈšîdlm¨uÖ‚ÓîÉ÷¾î÷¼ð;æûìz’Tv4û±Õ]އi¾žTúÄû7 ÍÖÝÎ{»…>nÛLÝÃyšJ][tg6ðÉ>ûï{Û· o>¾@{¼ç” Þ½ïkl`l¬;ÞïI_-E×Ö¹®ÜäFÚ ÝØìHUØÔ9`¶I_m@‘)PïaÕÙ ØbS¬JJ´Ð4VѲ‘UC^v+ `UI_N¹ B F@ª(›RÚ½4ªëeª»ÖäR{ãáw´ °t0HD+JbHMƒPSë®,×\ãèéy»º =
hÈ@T9ê(_k0MW¯j›½9ßx‡{×{êØÐôt ÷NÍ>Ø£´^¶ûqmÜ€Ö{Žì.fµ—f{½îkxÒ{Ü÷{o<õ²}ؘ Ú°êÇæ´ÅêÛï;ï»ÝßwžíöeúCBÙÝ…
+Ð om¶=n†€
&ØÜ΢‡¢»Ø ªK7@öŠõ‹Þï;ï{×’Õ¾ìç¹Ê÷fö°t
ú
9
ô=êŒwÝx\¯sÖ”í–úÕ5’m€ÔßN«;•Q_fÝó½ß7Ax:{>û΋Yõ´>€g{¼MíÖöÌûpòC¶·³§F
ÇÓϽƒï¯cç€ÔÙPzÐ 7`u îîCo[Û}÷¾ÇÓ>íË_yË'q¾Ø :Éî{»zËcÏ·”Âóé÷“ÛâÏÛR†uœ€h
¾}|j÷Û¾½TùÉî}¶”wnûÜò¶÷píí÷½Çg[jûyÚ龬o¾—;ï¹õ§
phÁNžÚúßU;i{i^C^¶¹îžcqW»§7ußxt½‹>ã½íx]÷r˜ú}îî½Þ÷ÜÏ·ZvÝo5yo{¯`·Ý5Ì¥ÇnÛ*½¼í‹ßpï½unÀ¾‰xõ÷yæÓB—©wßG¾ÀvîãTìÄO½Œ}Ͻ—Óë5Žñ\™{ÛuÚFƒ]7ò}kÝî<ù÷¾¼{»Üís¹¥Ù¾÷¯Nú=®óyæÇ_}÷i¥-˜ H ûæ0Ûžƒ½¶Üv£»=÷»ëƒ±{ÝYï|uã¯}¼¶ßWÇ®o»rñÖÇT¥LÞîíPVPw]–»÷ß=Wmë}=t!ëÓwÓºnÕ¤ªÞ;¶Ýž«Ãͼ®í¾ãß{w5îu>wϤo· }•(UröéÛ*âøçŽÏh•Ûí7¯yrÜëã¼½Iµ-N»ìú}7Í÷-âYÞÌ÷É×kfXíÙ×½ÍÑ<:õwÜûÇbªµÊW}i÷£†¯¬û¾ßQצû¸V÷ß=ht·Ý>ù¯.Þ÷ÝNϽz뼇Ôù‹
‡ÕÓ1-¹°EGMš£wDç÷yÀT@¥ ¥—GqÞð2uxãÅzæùðûÑ®ìÍ´»¾ïópßwYƒ|öÞµ÷exÛÊJ·Zº÷Íx
›}º§&—Z@( í€
NÇ`
׸‹Û^Õ"•íôªÎÛ¾¼Ö°¾ 4¶=ÝôËíïq½¸Æûº_^ûÝÛX·¾»«ÜË{Å©¸ÜÚÔnÖú>vù½ÁÀ=]x–ò¹÷½Ïç1{wžÁrݵ¢3ï>ï»ë¾çº]Δ³× úZäjSy±Ý÷/}ÖÅzQ÷;”›ë×{Û}çGì¤Û×kºêËmÛGYÁ‹`îÕ “®¶{Ïzö`•Ž…-µ¨y®|Ëw{å¦îúÞÝs}%"ï
ž³oFìÌÇEb^Þ¥_8>€£¾ú–'¦®@
Z)€}ÎíûWµK—nmvÝ·Vû²w±äH Á.Û®0öÙ¯g¶ã×Ohj¥YÍ›½zøï5ï£i¼lÛ[SºÒ
µ.²æÁ´=v÷+½0]Þ<½Ý(qpêfY3ëÏfM{¹Am–Ð@
og¤“ƒuî½X¸‰A%^Jr`ÝWca¥lÖr …:swUÙËÛ/nu½íÓÞnÇc6˜»ÛÞ=²CM+X®Äföðr]žå¶ž¯ÕsjñjÎnvÛ›àôsN¼ææ4ös5½{»Ï]a÷95ä{fóK‚©Å*( ”Ûë¶:ÝÓ©©—¡Ž´°»š×mÆí—¶½5“·N=Á×V¢[‡3Gv× ½@ݺ¾ï@ zT4 “·Û
ç^Q-àuÛí®E÷aÍí{=‹^½·}³ÛÙ¾ö/_líjßwuÜ€ûÝEÛÕÙSMúﯾà>í§ª z
€ )ôhhäÝ8uÜÈݾêàWƒ»^'¶æÚvÁÕrjÛ]W—€94o³"sŹKX|ÚËu©4¶ç6¸8;R:ÂÎÜÃ+’¢§1-]Û³m†µvd}÷^¡©*aï–Ù¨·
Ý<ò ÝóïÙï‹¥ÄáËN B 4 M ‘ &‰¦Mi¦„Âd4£@ h ”Ð@AA #DÁ&ÐÉ”ò˜&˜FLšž¦)¦MQ“Ô¨ 4 “EDЄÑ0TóTôÚ5dhÓSLØ™=SÓSÊd42=M4ɦš4z€4 ÐÐ ˆ‚SÔÈÈ™•Rèȧª~iSý§þ¥GŸ©êž£&Ÿ©µ=AêmQ´= ¤6‰€ š1`!I@@Mj`ŒA‰F¦ðLôÔÀ©í4ô5'¡Fž$Ñ“jŒšd
z ‰ M ÐSdÉšbiè’¨Ê4 qóü°dä?ê¿göõ÷vþŸðþŸ§šÜÝÀ\û§Æ#›$!êWñ?§õöþÏ×&g\×8…ç5‹ÄÓzÍ¿¯$çH "Ð¥y¡[)JD M“)8 ¸@Lp ,
xõ€c·‡†jâ9³üÓJd™´â{»ÜéÂùÌÀ²*RT¬"Ò,JL1DGF™}¹UÔ
Ò"$„ª”¦@"ÿÉ‘Ô
¸B…É ö“ý©_zKÄ‚ ĈŸå:ÌØ(œŸ‡óð8<‘¾¢#¡N Ñ‘4JH´
Pˆ¡h?^ŠŠhQ)T
´":„)€WL¨¹Ä"p À 0ˆ)‚\! J„® M šBSp
¦ˆ hÚæ ©E\”i¥P
.à~£&D7c-ȤŠÂ"ŽÊô:×ùÏÈl_ú-Ä#Aü·éuŽ?‹]äŠ
ŸT0‘" ¡˜`™%H`f
V€ ¥"ˆE9HrSüª’9(×î9›‰„…($8†!úî/Î ˆwBDW†ìyÝ8:„ ô—nÊ M.œÐ#˜>Qˆskf(†ÈDÉÉJPöÊh…D)„£BR‰Í&¤) 0•=hgaúk›ý,áU2³*q¸D¥ÌRi$‘þâ^µü'þÓ ©¤ø÷ì/-™†?[¤£ýßòã.¸º¾~O ´=ÞNqg¸XEõØÑ¿èë{ôµõªÒÐóˆ£ÿq W‹
—guLŠH1:0ÊÒOsË^æKQoùgÛ˜KŒå5Û«%g¿v!"Ìar›¯}1?ðþ³Xã]±¦qý³þªu…ðÀ3›ÿTõh乌À(]«;›sÝR"¯Å^(
<
#÷Š%ÿ
d£Â…N7jœ‹MÚe£m7Å•UîSøåQ-“