aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSilvio Rhatto <rhatto@riseup.net>2011-01-22 18:24:55 -0200
committerSilvio Rhatto <rhatto@riseup.net>2011-01-22 18:24:55 -0200
commit7382be9d83bc5f95ad8d184b95c379ca5b9d1725 (patch)
tree5ad086f30f59f22e27d427cab1e30ef5282ddbf0
parent42fdb4e702f1235ad6f4ae099f8d265e498a62d4 (diff)
downloadkeyringer-7382be9d83bc5f95ad8d184b95c379ca5b9d1725.tar.gz
keyringer-7382be9d83bc5f95ad8d184b95c379ca5b9d1725.tar.bz2
Code split into backend, keyring and keyringer modules
-rwxr-xr-xbin/keyringer30
-rw-r--r--lib/backend.rb3
-rw-r--r--lib/backend/crypt.rb159
-rw-r--r--lib/keyring.rb5
-rw-r--r--lib/keyring/crypt.rb10
-rw-r--r--lib/keyring/fs.rb (renamed from lib/keyringer/fs.rb)2
-rw-r--r--lib/keyringer.rb9
-rw-r--r--lib/keyringer/bash_wrapper.rb7
-rw-r--r--lib/keyringer/crypt.rb158
-rw-r--r--lib/keyringer/decrypt.rb10
10 files changed, 213 insertions, 180 deletions
diff --git a/bin/keyringer b/bin/keyringer
index 974fa80..74dfcb1 100755
--- a/bin/keyringer
+++ b/bin/keyringer
@@ -9,31 +9,19 @@ def usage
exit 1
end
-# TODO: misc checks
-def doDecrypt(someArguments)
- filename = ARGV[2]
- file = Keyringer::Fs.new()
- content = file.get_as_string(filename)
-
- crypt = Keyringer::Crypt.new(nil)
- output = crypt.decrypt(content)
- puts output
-end
-
-def doWrapper(someArguments)
- exec("keyringer " + ARGV.join(' '))
-end
-
$:.unshift File.dirname(__FILE__) + '/../lib'
require 'keyringer'
begin
- keyring = ARGV[0]
- action = ARGV[1]
- if action == 'decrypt'
- doDecrypt(ARGV)
- else
- doWrapper(ARGV)
+ action = Keyringer.const_get(ARGV[1].capitalize)
+
+ if action.is_a?(Class)
+ instance = action.new
+ output = instance.execute
+ puts output
end
+rescue NameError
+ wrapper = Keyringer::BashWrapper.new
+ wrapper.execute
rescue SystemExit => e
exit e.status
rescue Exception => e
diff --git a/lib/backend.rb b/lib/backend.rb
new file mode 100644
index 0000000..18f220c
--- /dev/null
+++ b/lib/backend.rb
@@ -0,0 +1,3 @@
+# internal requires
+$:.unshift File.dirname(__FILE__)
+require 'backend/crypt'
diff --git a/lib/backend/crypt.rb b/lib/backend/crypt.rb
new file mode 100644
index 0000000..2f00515
--- /dev/null
+++ b/lib/backend/crypt.rb
@@ -0,0 +1,159 @@
+# This code is based on the library from http://schleuder2.nadir.org/
+require 'gpgme'
+
+module Backend
+ # Wrapper for ruby-gpgme. Method naming is not strictly logical, this might
+ # change but aliases will be set up then.
+ class Crypt
+ # Instantiates and stores password
+ def initialize(password)
+ @password = password
+ @ctx = GPGME::Ctx.new
+ # feed the passphrase into the Context
+ @ctx.set_passphrase_cb(method(:passfunc))
+ end
+
+ # TODO: use a logging facility
+ def debug(message)
+ puts message
+ end
+
+ # TODO: use a logging facility
+ def error(message)
+ puts message
+ end
+
+ # Verify a gpg-signature. Use +signed_string+ if the signature is
+ # detached. Returns a GPGME::SignatureResult
+ def verify(sig, signed_string='')
+ in_signed = ''
+ if signed_string.empty?
+ # verify +sig+ as cleartext (aka pgp/inline) signature
+ debug 'No extra signed_string, verifying cleartext signature'
+ output = GPGME.verify(sig) do |sig|
+ in_signed = sig
+ end
+ else
+ # verify detached signature
+ debug 'Verifying detached signature'
+ # Don't know why we need a GPGME::Data object this time but without gpgme throws exceptions
+ plain = GPGME::Data.new
+ GPGME.verify(sig, signed_string, plain) do |sig|
+ in_signed = sig
+ end
+ output = signed_string
+
+ end
+ debug 'verify_result: ' + in_signed.inspect
+
+ [output, in_signed]
+ end
+
+ # Decrypt a string.
+ def decrypt(str)
+ output = ""
+ in_encrypted = nil
+ in_signed = nil
+
+ # TODO: return ciphertext if missing key. Sensible e.g. if it is part
+ # of a nested MIME-message and encrypted to someone else on purpose.
+ # Breaking if even the whole message is not decryptable is a job for
+ # the processor.
+
+ # return input instead of empty String if not encrypted
+ unless str =~ /^-----BEGIN PGP MESSAGE-----/
+ # match pgp-mime- and inline-pgp-signatures
+ if str =~ /^-----BEGIN PGP SIG/
+ debug 'found signed, not encrypted message, verifying'
+ output, in_signed = verify(str)
+ else
+ debug 'found not signed, not encrypted message, returning input'
+ output = str
+ end
+ else
+ debug 'found pgp content, decrypting and verifying with gpgme'
+ in_encrypted = true
+ output = GPGME.decrypt(str, :passphrase_callback => method(:passfunc)) do |sig|
+ in_signed = sig
+ end
+ if output.empty?
+ Exception.new("Output from GPGME.decrypt was empty!")
+ end
+ # TODO: return mailadresses or keys instead of signature-objects?
+ end
+ [output, in_encrypted, in_signed]
+ end
+
+ # Encrypt a string to a single receiver and sign it. +receiver+ must be a
+ # Keyringer::Member
+ def encrypt_str(str, receiver)
+ # encypt and sign and return encrypted data as string
+ key = receiver.key || receiver.email
+ GPGME.encrypt([key], str, {:passphrase_callback => method(:passfunc), :armor => true, :sign => true, :always_trust => true})
+ end
+
+ # Lists all public keys matching +pattern+. Returns an array of
+ # GPGME::GpgKey's
+ def list_keys(pattern='')
+ GPGME.list_keys(pattern)
+ end
+
+ # Returns the GPGME::GpgKey matching +pattern+. Log an error if more than
+ # one matches, because duplicated user-ids is a sensitive issue.
+ def get_key(pattern)
+ pattern = "<#{pattern}>" if pattern =~ /.*@.*/
+ k = list_keys(pattern)
+ if k.length > 1
+ error "There's more than one key matching the pattern you gave me!\nPattern: #{pattern}\nkeys: #{k.inspect}"
+ false
+ else
+ k.first
+ end
+ end
+
+ # Signs +string+ with the private key of the list (aka detached signature)
+ def sign(string)
+ GPGME::detach_sign(string, {:armor => true, :passphrase_callback => method(:passfunc)})
+ end
+
+ # Clearsigns +string+ with the private key of the list
+ def clearsign(string)
+ GPGME::clearsign(string, {:armor => true, :passphrase_callback => method(:passfunc)})
+ end
+
+ # Exports the public key matching +keyid+ as ascii key block.
+ def export(keyid)
+ GPGME.export(keyid, :armor=>:true)
+ end
+
+ # Delete the public key matching +pattern+ from the public key ring of the
+ # list
+ def delete_key(key)
+ key = get_key(key) if key.kind_of?(String)
+ begin
+ @ctx.delete_key(key)
+ return true
+ rescue => e
+ return e
+ end
+ end
+
+ # Import +keydata+ into public key ring of the list
+ def add_key(keydata)
+ GPGME.import(keydata)
+ end
+
+ def add_key_from_file(keyfile)
+ add_key(File.read(keyfile))
+ end
+
+ private
+
+ def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
+ io = IO.for_fd(fd, 'w')
+ io.puts @password
+ io.flush
+ end
+
+ end
+end
diff --git a/lib/keyring.rb b/lib/keyring.rb
new file mode 100644
index 0000000..7bfdb86
--- /dev/null
+++ b/lib/keyring.rb
@@ -0,0 +1,5 @@
+# internal requires
+$:.unshift File.dirname(__FILE__)
+require 'backend'
+require 'keyring/crypt'
+require 'keyring/fs'
diff --git a/lib/keyring/crypt.rb b/lib/keyring/crypt.rb
new file mode 100644
index 0000000..5968730
--- /dev/null
+++ b/lib/keyring/crypt.rb
@@ -0,0 +1,10 @@
+module Keyring
+ class Crypt
+ def decrypt(filename)
+ file = Fs.new()
+ content = file.get_as_string(filename)
+ crypt = Backend::Crypt.new(nil)
+ return crypt.decrypt(content)
+ end
+ end
+end
diff --git a/lib/keyringer/fs.rb b/lib/keyring/fs.rb
index 7b7742a..9f20378 100644
--- a/lib/keyringer/fs.rb
+++ b/lib/keyring/fs.rb
@@ -1,4 +1,4 @@
-module Keyringer
+module Keyring
class Fs
def get_as_string(filename)
data = ''
diff --git a/lib/keyringer.rb b/lib/keyringer.rb
new file mode 100644
index 0000000..9d455d1
--- /dev/null
+++ b/lib/keyringer.rb
@@ -0,0 +1,9 @@
+# internal requires
+$:.unshift File.dirname(__FILE__)
+require 'keyring'
+require 'keyringer/decrypt'
+require 'keyringer/bash_wrapper'
+
+module Keyring
+ VERSION = '2.0-alpha'
+end
diff --git a/lib/keyringer/bash_wrapper.rb b/lib/keyringer/bash_wrapper.rb
new file mode 100644
index 0000000..ba4b4d0
--- /dev/null
+++ b/lib/keyringer/bash_wrapper.rb
@@ -0,0 +1,7 @@
+module Keyringer
+ class BashWrapper
+ def execute
+ exec("keyringer " + ARGV.join(' '))
+ end
+ end
+end
diff --git a/lib/keyringer/crypt.rb b/lib/keyringer/crypt.rb
deleted file mode 100644
index 1ec4126..0000000
--- a/lib/keyringer/crypt.rb
+++ /dev/null
@@ -1,158 +0,0 @@
-require 'gpgme'
-
-module Keyringer
- # Wrapper for ruby-gpgme. Method naming is not strictly logical, this might
- # change but aliases will be set up then.
- class Crypt
- # Instantiates and stores password
- def initialize(password)
- @password = password
- @ctx = GPGME::Ctx.new
- # feed the passphrase into the Context
- @ctx.set_passphrase_cb(method(:passfunc))
- end
-
- # TODO: use a logging facility
- def debug(message)
- puts message
- end
-
- # TODO: use a logging facility
- def error(message)
- puts message
- end
-
- # Verify a gpg-signature. Use +signed_string+ if the signature is
- # detached. Returns a GPGME::SignatureResult
- def verify(sig, signed_string='')
- in_signed = ''
- if signed_string.empty?
- # verify +sig+ as cleartext (aka pgp/inline) signature
- debug 'No extra signed_string, verifying cleartext signature'
- output = GPGME.verify(sig) do |sig|
- in_signed = sig
- end
- else
- # verify detached signature
- debug 'Verifying detached signature'
- # Don't know why we need a GPGME::Data object this time but without gpgme throws exceptions
- plain = GPGME::Data.new
- GPGME.verify(sig, signed_string, plain) do |sig|
- in_signed = sig
- end
- output = signed_string
-
- end
- debug 'verify_result: ' + in_signed.inspect
-
- [output, in_signed]
- end
-
- # Decrypt a string.
- def decrypt(str)
- output = ""
- in_encrypted = nil
- in_signed = nil
-
- # TODO: return ciphertext if missing key. Sensible e.g. if it is part
- # of a nested MIME-message and encrypted to someone else on purpose.
- # Breaking if even the whole message is not decryptable is a job for
- # the processor.
-
- # return input instead of empty String if not encrypted
- unless str =~ /^-----BEGIN PGP MESSAGE-----/
- # match pgp-mime- and inline-pgp-signatures
- if str =~ /^-----BEGIN PGP SIG/
- debug 'found signed, not encrypted message, verifying'
- output, in_signed = verify(str)
- else
- debug 'found not signed, not encrypted message, returning input'
- output = str
- end
- else
- debug 'found pgp content, decrypting and verifying with gpgme'
- in_encrypted = true
- output = GPGME.decrypt(str, :passphrase_callback => method(:passfunc)) do |sig|
- in_signed = sig
- end
- if output.empty?
- Exception.new("Output from GPGME.decrypt was empty!")
- end
- # TODO: return mailadresses or keys instead of signature-objects?
- end
- [output, in_encrypted, in_signed]
- end
-
- # Encrypt a string to a single receiver and sign it. +receiver+ must be a
- # Keyringer::Member
- def encrypt_str(str, receiver)
- # encypt and sign and return encrypted data as string
- key = receiver.key || receiver.email
- GPGME.encrypt([key], str, {:passphrase_callback => method(:passfunc), :armor => true, :sign => true, :always_trust => true})
- end
-
- # Lists all public keys matching +pattern+. Returns an array of
- # GPGME::GpgKey's
- def list_keys(pattern='')
- GPGME.list_keys(pattern)
- end
-
- # Returns the GPGME::GpgKey matching +pattern+. Log an error if more than
- # one matches, because duplicated user-ids is a sensitive issue.
- def get_key(pattern)
- pattern = "<#{pattern}>" if pattern =~ /.*@.*/
- k = list_keys(pattern)
- if k.length > 1
- error "There's more than one key matching the pattern you gave me!\nPattern: #{pattern}\nkeys: #{k.inspect}"
- false
- else
- k.first
- end
- end
-
- # Signs +string+ with the private key of the list (aka detached signature)
- def sign(string)
- GPGME::detach_sign(string, {:armor => true, :passphrase_callback => method(:passfunc)})
- end
-
- # Clearsigns +string+ with the private key of the list
- def clearsign(string)
- GPGME::clearsign(string, {:armor => true, :passphrase_callback => method(:passfunc)})
- end
-
- # Exports the public key matching +keyid+ as ascii key block.
- def export(keyid)
- GPGME.export(keyid, :armor=>:true)
- end
-
- # Delete the public key matching +pattern+ from the public key ring of the
- # list
- def delete_key(key)
- key = get_key(key) if key.kind_of?(String)
- begin
- @ctx.delete_key(key)
- return true
- rescue => e
- return e
- end
- end
-
- # Import +keydata+ into public key ring of the list
- def add_key(keydata)
- GPGME.import(keydata)
- end
-
- def add_key_from_file(keyfile)
- add_key(File.read(keyfile))
- end
-
- private
-
- def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
- io = IO.for_fd(fd, 'w')
- io.puts @password
- io.flush
- end
-
- end
-end
diff --git a/lib/keyringer/decrypt.rb b/lib/keyringer/decrypt.rb
new file mode 100644
index 0000000..9f872aa
--- /dev/null
+++ b/lib/keyringer/decrypt.rb
@@ -0,0 +1,10 @@
+module Keyringer
+ class Decrypt
+ def execute
+ filename = ARGV[2]
+ crypt = Keyring::Crypt.new
+ output = crypt.decrypt(filename)
+ return output
+ end
+ end
+end