import gpgme import os from StringIO import StringIO class GPG2Signer(object): """ Helper class for signing data using GPG2. """ def __init__(self, app, key_directory): if not app.config.get('GPG2_PRIVATE_KEY_NAME'): raise Exception('Missing configuration key GPG2_PRIVATE_KEY_NAME') if not app.config.get('GPG2_PRIVATE_KEY_FILENAME'): raise Exception('Missing configuration key GPG2_PRIVATE_KEY_FILENAME') if not app.config.get('GPG2_PUBLIC_KEY_FILENAME'): raise Exception('Missing configuration key GPG2_PUBLIC_KEY_FILENAME') self._ctx = gpgme.Context() self._ctx.armor = True self._private_key_name = app.config['GPG2_PRIVATE_KEY_NAME'] self._public_key_path = os.path.join(key_directory, app.config['GPG2_PUBLIC_KEY_FILENAME']) key_file = os.path.join(key_directory, app.config['GPG2_PRIVATE_KEY_FILENAME']) if not os.path.exists(key_file): raise Exception('Missing key file %s' % key_file) with open(key_file, 'rb') as fp: self._ctx.import_(fp) @property def name(self): return 'gpg2' @property def public_key_path(self): return self._public_key_path def detached_sign(self, stream): """ Signs the given stream, returning the signature. """ ctx = self._ctx ctx.signers = [ctx.get_key(self._private_key_name)] signature = StringIO() new_sigs = ctx.sign(stream, signature, gpgme.SIG_MODE_DETACH) signature.seek(0) return signature.getvalue() class Signer(object): def __init__(self, app=None, key_directory=None): self.app = app if app is not None: self.state = self.init_app(app, key_directory) else: self.state = None def init_app(self, app, key_directory): preference = app.config.get('SIGNING_ENGINE', None) if preference is None: return None return SIGNING_ENGINES[preference](app, key_directory) def __getattr__(self, name): return getattr(self.state, name, None) SIGNING_ENGINES = { 'gpg2': GPG2Signer }