コード例 #1
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def signContent(self, content, key, password='', mode=None):
        """See IGPGHandler."""
        if not isinstance(content, str):
            raise TypeError('Content should be a string.')

        if mode is None:
            mode = gpgme.SIG_MODE_CLEAR

        # Find the key and make it the only one allowed to sign content
        # during this session.
        context = get_gpgme_context()
        context.signers = [removeSecurityProxy(key.key)]

        # Set up containers.
        plaintext = StringIO(content)
        signature = StringIO()

        # Make sure that gpg-agent doesn't interfere.
        if 'GPG_AGENT_INFO' in os.environ:
            del os.environ['GPG_AGENT_INFO']

        def passphrase_cb(uid_hint, passphrase_info, prev_was_bad, fd):
            os.write(fd, '%s\n' % password)

        context.passphrase_cb = passphrase_cb

        # Sign the text.
        try:
            with gpgme_timeline("sign", key.fingerprint):
                context.sign(plaintext, signature, mode)
        except gpgme.GpgmeError:
            return None

        return signature.getvalue()
コード例 #2
0
ファイル: __init__.py プロジェクト: pombredanne/launchpad-3
def decrypt_content(content, password):
    """Return the decrypted content or None if failed

    content and password must be traditional strings. It's up to
    the caller to encode or decode properly.

    :content: encrypted data content
    :password: unicode password to unlock the secret key in question
    """
    if isinstance(password, unicode):
        raise TypeError('Password cannot be Unicode.')

    if isinstance(content, unicode):
        raise TypeError('Content cannot be Unicode.')

    ctx = get_gpgme_context()

    # setup containers
    cipher = StringIO(content)
    plain = StringIO()

    def passphrase_cb(uid_hint, passphrase_info, prev_was_bad, fd):
        os.write(fd, '%s\n' % password)

    ctx.passphrase_cb = passphrase_cb

    # Do the decryption.
    try:
        ctx.decrypt(cipher, plain)
    except gpgme.GpgmeError:
        return None

    return plain.getvalue()
コード例 #3
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def generateKey(self, name):
        """See `IGPGHandler`."""
        context = get_gpgme_context()

        # Make sure that gpg-agent doesn't interfere.
        if 'GPG_AGENT_INFO' in os.environ:
            del os.environ['GPG_AGENT_INFO']

        # Only 'utf-8' encoding is supported by gpgme.
        # See more information at:
        # http://pyme.sourceforge.net/doc/gpgme/Generating-Keys.html
        with gpgme_timeline("genkey", name):
            result = context.genkey(signing_only_param %
                                    {'name': name.encode('utf-8')})

        # Right, it might seem paranoid to have this many assertions,
        # but we have to take key generation very seriously.
        assert result.primary, 'Secret key generation failed.'
        assert not result.sub, (
            'Only sign-only RSA keys are safe to be generated')

        secret_keys = list(self.localKeys(result.fpr, secret=True))

        assert len(secret_keys) == 1, 'Found %d secret GPG keys for %s' % (
            len(secret_keys), result.fpr)

        key = secret_keys[0]

        assert key.fingerprint == result.fpr, (
            'The key in the local keyring does not match the one generated.')
        assert key.exists_in_local_keyring, (
            'The key does not seem to exist in the local keyring.')

        return key
コード例 #4
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def importSecretKey(self, content):
        """See `IGPGHandler`."""
        assert isinstance(content, str)

        # Make sure that gpg-agent doesn't interfere.
        if 'GPG_AGENT_INFO' in os.environ:
            del os.environ['GPG_AGENT_INFO']

        context = get_gpgme_context()
        newkey = StringIO(content)
        with gpgme_timeline("import", "new secret key"):
            import_result = context.import_(newkey)

        secret_imports = [
            fingerprint
            for fingerprint, result, status in import_result.imports
            if status & gpgme.IMPORT_SECRET
        ]
        if len(secret_imports) != 1:
            raise MoreThanOneGPGKeyFound(
                'Found %d secret GPG keys when importing %s' %
                (len(secret_imports), content))

        fingerprint, result, status = import_result.imports[0]
        try:
            key = context.get_key(fingerprint, True)
        except gpgme.GpgmeError:
            return None

        key = PymeKey.newFromGpgmeKey(key)
        assert key.exists_in_local_keyring
        return key
コード例 #5
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def importPublicKey(self, content):
        """See IGPGHandler."""
        assert isinstance(content, str)
        context = get_gpgme_context()

        newkey = StringIO(content)
        with gpgme_timeline("import", "new public key"):
            result = context.import_(newkey)

        if len(result.imports) == 0:
            raise GPGKeyNotFoundError(content)

        # Check the status of all imported keys to see if any of them is
        # a secret key.  We can't rely on result.secret_imported here
        # because if there's a secret key which is already imported,
        # result.secret_imported will be 0.
        for fingerprint, res, status in result.imports:
            if status & gpgme.IMPORT_SECRET != 0:
                raise SecretGPGKeyImportDetected(
                    "GPG key '%s' is a secret key." % fingerprint)

        if len(result.imports) > 1:
            raise MoreThanOneGPGKeyFound(
                'Found %d GPG keys when importing %s' %
                (len(result.imports), content))

        fingerprint, res, status = result.imports[0]
        key = PymeKey(fingerprint)
        assert key.exists_in_local_keyring
        return key
コード例 #6
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def _buildFromFingerprint(self, fingerprint):
        """Build key information from a fingerprint."""
        context = get_gpgme_context()
        # retrive additional key information
        try:
            with gpgme_timeline("get-key", fingerprint):
                key = context.get_key(fingerprint, False)
        except gpgme.GpgmeError:
            key = None

        if key and valid_fingerprint(key.subkeys[0].fpr):
            self._buildFromGpgmeKey(key)
コード例 #7
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def localKeys(self, filter=None, secret=False):
        """Get an iterator of the keys this gpg handler
        already knows about.
        """
        ctx = get_gpgme_context()

        # XXX michaeln 2010-05-07 bug=576405
        # Currently gpgme.Context().keylist fails if passed a unicode
        # string even though that's what is returned for fingerprints.
        if type(filter) == unicode:
            filter = filter.encode('utf-8')

        with gpgme_timeline("keylist",
                            "filter: %r, secret: %r" % (filter, secret)):
            for key in ctx.keylist(filter, secret):
                yield PymeKey.newFromGpgmeKey(key)
コード例 #8
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def getVerifiedSignature(self, content, signature=None):
        """See IGPGHandler."""

        assert not isinstance(content, unicode)
        assert not isinstance(signature, unicode)

        ctx = get_gpgme_context()

        # We may not yet have the public key, so find out the fingerprint we
        # need to fetch.
        _, sig = self._rawVerifySignature(ctx, content, signature=signature)

        # Fetch the full key from the keyserver now that we know its
        # fingerprint, and then verify the signature again.  (This also lets
        # us support subkeys by using the master key fingerprint.)
        # XXX cjwatson 2019-03-12: Before GnuPG 2.2.7 and GPGME 1.11.0,
        # sig.fpr is a 64-bit key ID in the case where the key isn't in the
        # local keyring yet.  I haven't yet heard of 64-bit key ID
        # collisions in the wild, but even if they happen here,
        # importPublicKey will raise MoreThanOneGPGKeyFound, so the worst
        # consequence is a denial of service for the owner of an affected
        # key.  If we do run into this, then the correct fix is to upgrade
        # GnuPG and GPGME.
        key = self.retrieveKey(sig.fpr)
        plain, sig = self._rawVerifySignature(ctx,
                                              content,
                                              signature=signature)

        expired = False
        # sig.status == 0 means "Ok"
        if sig.status is not None:
            if sig.status.code == gpgme.ERR_KEY_EXPIRED:
                expired = True
            else:
                raise GPGVerificationError(sig.status.args)

        if expired:
            # This should already be set, but let's make sure.
            key.expired = True
            raise GPGKeyExpired(key)

        # return the signature container
        return PymeSignature(fingerprint=key.fingerprint,
                             plain_data=plain.getvalue(),
                             timestamp=sig.timestamp)
コード例 #9
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def export(self):
        """See `IPymeKey`."""
        if self.secret:
            # XXX cprov 20081014: gpgme_op_export() only supports public keys.
            # See http://www.fifi.org/cgi-bin/info2www?(gpgme)Exporting+Keys
            p = subprocess.Popen([
                get_gpg_path(), '--export-secret-keys', '-a', self.fingerprint
            ],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
            return p.stdout.read()

        context = get_gpgme_context()
        keydata = StringIO()
        with gpgme_timeline("export", self.fingerprint):
            context.export(self.fingerprint.encode('ascii'), keydata)

        return keydata.getvalue()
コード例 #10
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
 def retrieveKey(self, fingerprint):
     """See IGPGHandler."""
     # XXX cprov 2005-07-05:
     # Integrate it with the furure proposal related
     # synchronization of the local key ring with the
     # global one. It should basically consists of be
     # aware of a revoked flag coming from the global
     # key ring, but it needs "specing"
     key = PymeKey(fingerprint.encode('ascii'))
     if not key.exists_in_local_keyring:
         pubkey = self._getPubKey(fingerprint)
         key = self.importPublicKey(pubkey)
         if not key.matches(fingerprint):
             ctx = get_gpgme_context()
             with gpgme_timeline("delete", key.fingerprint):
                 ctx.delete(key.key)
             raise GPGKeyMismatchOnServer(fingerprint, key.fingerprint)
     return key
コード例 #11
0
ファイル: handler.py プロジェクト: pombredanne/launchpad-3
    def encryptContent(self, content, key):
        """See IGPGHandler."""
        if isinstance(content, unicode):
            raise TypeError('Content cannot be Unicode.')

        ctx = get_gpgme_context()

        # setup containers
        plain = StringIO(content)
        cipher = StringIO()

        if key.key is None:
            return None

        if not key.can_encrypt:
            raise ValueError('key %s can not be used for encryption' %
                             key.fingerprint)

        # encrypt content
        with gpgme_timeline("encrypt", key.fingerprint):
            ctx.encrypt([removeSecurityProxy(key.key)],
                        gpgme.ENCRYPT_ALWAYS_TRUST, plain, cipher)

        return cipher.getvalue()