Ejemplo n.º 1
0
    def merge(self, newkey):
        if newkey.fingerprint != self.fingerprint:
            logger.critical(
                "Can't put a key whith the same key_id and different "
                "fingerprint: %s, %s" % (newkey.fingerprint, self.fingerprint))
            raise errors.KeyFingerprintMismatch(newkey.fingerprint)

        with TempGPGWrapper(gpgbinary=self._gpgbinary) as gpg:
            gpg.import_keys(self.key_data)
            gpg.import_keys(newkey.key_data)
            gpgkey = gpg.list_keys(secret=newkey.private).pop()

            if gpgkey['expires']:
                self.expiry_date = datetime.fromtimestamp(
                    int(gpgkey['expires']))
            else:
                self.expiry_date = None

            self.uids = []
            for uid in gpgkey['uids']:
                self.uids.append(parse_address(uid))

            self.length = int(gpgkey['length'])
            self.key_data = gpg.export_keys(gpgkey['fingerprint'],
                                            secret=self.private)

        if newkey.validation > self.validation:
            self.validation = newkey.validation
        if newkey.last_audited_at > self.last_audited_at:
            self.validation = newkey.last_audited_at
        self.encr_used = newkey.encr_used or self.encr_used
        self.sign_used = newkey.sign_used or self.sign_used
        self.refreshed_at = datetime.now()
Ejemplo n.º 2
0
def process_key(key_data, gpgbinary, secret=False):
    with TempGPGWrapper(gpgbinary=gpgbinary) as gpg:
        try:
            gpg.import_keys(key_data)
            info = gpg.list_keys(secret=secret).pop()
            key = gpg.export_keys(info['fingerprint'], secret=secret)
        except IndexError:
            info = {}
            key = None
    return info, key
Ejemplo n.º 3
0
    def sign(self,
             data,
             privkey,
             digest_algo='SHA512',
             clearsign=False,
             detach=True,
             binary=False):
        """
        Sign C{data} with C{privkey}.

        :param data: The data to be signed.
        :type data: str

        :param privkey: The private key to be used to sign.
        :type privkey: OpenPGPKey
        :param digest_algo: The hash digest to use.
        :type digest_algo: str
        :param clearsign: If True, create a cleartext signature.
        :type clearsign: bool
        :param detach: If True, create a detached signature.
        :type detach: bool
        :param binary: If True, do not ascii armour the output.
        :type binary: bool

        :return: The ascii-armored signed data.
        :rtype: str
        """
        leap_assert_type(privkey, OpenPGPKey)
        leap_assert(privkey.private is True)

        # result.fingerprint - contains the fingerprint of the key used to
        #                      sign.
        with TempGPGWrapper(privkey, self._gpgbinary) as gpg:
            kw = dict(default_key=privkey.fingerprint,
                      digest_algo=digest_algo,
                      clearsign=clearsign,
                      detach=detach,
                      binary=binary)
            if not GNUPG_NG:
                kw.pop('digest_algo')
                kw.pop('default_key')
            result = gpg.sign(data, **kw)
            rfprint = privkey.fingerprint
            privkey = gpg.list_keys(secret=True).pop()
            kfprint = privkey['fingerprint']
            if result.fingerprint is None:
                raise errors.SignFailed(
                    'Failed to sign with key %s: %s' %
                    (privkey['fingerprint'], result.stderr))
            leap_assert(
                result.fingerprint == kfprint,
                'Signature and private key fingerprints mismatch: '
                '%s != %s' % (rfprint, kfprint))
        return result.data
Ejemplo n.º 4
0
    def encrypt(self,
                data,
                pubkey,
                passphrase=None,
                sign=None,
                cipher_algo='AES256'):
        """
        Encrypt C{data} using public @{pubkey} and sign with C{sign} key.

        :param data: The data to be encrypted.
        :type data: str
        :param pubkey: The key used to encrypt.
        :type pubkey: OpenPGPKey
        :param sign: The key used for signing.
        :type sign: OpenPGPKey
        :param cipher_algo: The cipher algorithm to use.
        :type cipher_algo: str

        :return: A Deferred that will be fired with the encrypted data.
        :rtype: defer.Deferred

        :raise EncryptError: Raised if failed encrypting for some reason.
        """
        leap_assert_type(pubkey, OpenPGPKey)
        leap_assert(pubkey.private is False, 'Key is not public.')
        keys = [pubkey]
        if sign is not None:
            leap_assert_type(sign, OpenPGPKey)
            leap_assert(sign.private is True)
            keys.append(sign)
        with TempGPGWrapper(keys, self._gpgbinary) as gpg:
            kw = dict(default_key=sign.fingerprint if sign else None,
                      passphrase=passphrase,
                      symmetric=False,
                      cipher_algo=cipher_algo)
            if not GNUPG_NG:
                kw.pop('cipher_algo')
                kw.pop('default_key')
                kw.update(passphrase='')
                kw.update(always_trust=True)
            result = yield from_thread(gpg.encrypt, data, pubkey.fingerprint,
                                       **kw)
            # Here we cannot assert for correctness of sig because the sig is
            # in the ciphertext.
            # result.ok    - (bool) indicates if the operation succeeded
            # result.data  - (bool) contains the result of the operation
            try:
                self._assert_gpg_result_ok(result)
                defer.returnValue(result.data)
            except errors.GPGError as e:
                self.log.warn('Failed to encrypt: %s.' % str(e))
                raise errors.EncryptError()
Ejemplo n.º 5
0
    def is_encrypted(self, data):
        """
        Return whether C{data} was asymmetrically encrypted using OpenPGP.

        :param data: The data we want to know about.
        :type data: str

        :return: Whether C{data} was encrypted using this wrapper.
        :rtype: bool
        """
        with TempGPGWrapper(gpgbinary=self._gpgbinary) as gpg:
            gpgutil = GPGUtilities(gpg)
            return gpgutil.is_encrypted_asym(data)
Ejemplo n.º 6
0
    def signatures(self):
        """
        Get the key signatures

        :return: the key IDs that have signed the key
        :rtype: list(str)
        """
        with TempGPGWrapper(keys=[self], gpgbinary=self._gpgbinary) as gpg:
            res = gpg.list_sigs(self.fingerprint)
            for uid, sigs in res.sigs.iteritems():
                if parse_address(uid) in self.uids:
                    return sigs

        return []
Ejemplo n.º 7
0
    def decrypt(self, data, privkey, passphrase=None, verify=None):
        """
        Decrypt C{data} using private @{privkey} and verify with C{verify} key.

        :param data: The data to be decrypted.
        :type data: str
        :param privkey: The key used to decrypt.
        :type privkey: OpenPGPKey
        :param passphrase: The passphrase for the secret key used for
                           decryption.
        :type passphrase: str
        :param verify: The key used to verify a signature.
        :type verify: OpenPGPKey

        :return: Deferred that will fire with the decrypted data and
                 if signature verifies (unicode, bool)
        :rtype: Deferred

        :raise DecryptError: Raised if failed decrypting for some reason.
        """
        leap_assert(privkey.private is True, 'Key is not private.')
        keys = [privkey]
        if verify is not None:
            leap_assert_type(verify, OpenPGPKey)
            leap_assert(verify.private is False)
            keys.append(verify)
        with TempGPGWrapper(keys, self._gpgbinary) as gpg:
            try:
                result = yield from_thread(gpg.decrypt,
                                           data,
                                           passphrase=passphrase,
                                           always_trust=True)
                self._assert_gpg_result_ok(result)

                # verify signature
                sign_valid = False
                if (verify is not None and result.valid is True
                        and verify.fingerprint == result.pubkey_fingerprint):
                    sign_valid = True

                defer.returnValue((result.data, sign_valid))
            except errors.GPGError as e:
                self.log.warn('Failed to decrypt: %s.' % str(e))
                raise errors.DecryptError(str(e))
Ejemplo n.º 8
0
        def _gen_key(_):
            with TempGPGWrapper(gpgbinary=self._gpgbinary) as gpg:
                # TODO: inspect result, or use decorator
                params = gpg.gen_key_input(
                    key_type='RSA',
                    key_length=4096,
                    name_real=address,
                    name_email=address,
                    name_comment='')
                logger.info("About to generate keys... "
                            "This might take SOME time.")
                yield from_thread(gpg.gen_key, params)
                logger.info("Keys for %s have been successfully "
                            "generated." % (address,))
                pubkeys = gpg.list_keys()

                # assert for new key characteristics
                leap_assert(
                    len(pubkeys) is 1,  # a unitary keyring!
                    'Keyring has wrong number of keys: %d.' % len(pubkeys))
                key = gpg.list_keys(secret=True).pop()
                leap_assert(
                    len(key['uids']) is 1,  # with just one uid!
                    'Wrong number of uids for key: %d.' % len(key['uids']))
                uid_match = False
                for uid in key['uids']:
                    if re.match('.*<%s>$' % address, uid) is not None:
                        uid_match = True
                        break
                leap_assert(uid_match, 'Key not correctly bound to address.')

                # insert both public and private keys in storage
                deferreds = []
                for secret in [True, False]:
                    key = gpg.list_keys(secret=secret).pop()
                    openpgp_key = self._build_key_from_gpg(
                        key,
                        gpg.export_keys(key['fingerprint'], secret=secret),
                        address)
                    d = self.put_key(openpgp_key)
                    deferreds.append(d)
                yield defer.gatherResults(deferreds)
Ejemplo n.º 9
0
    def is_signed_by(self, other_key):
        """
        Checks if current key was signed by another key. Rather than just
        relying on the fingerprint being there, we use gpg's --check-sigs with
        both keys being present in the keychain to check the signature
        validity. By doing so, relying on the long key id instead of the
        fingerprint is fine.

        :param other_key: the other key.
        :return: True if valid signature could be found.
        :rtype: bool
        """
        keys = [self, other_key]
        with TempGPGWrapper(keys=keys, gpgbinary=self._gpgbinary) as gpg:
            certs = gpg.check_sigs(str(self.fingerprint)).certs
            for uid, cur_certs in certs.iteritems():
                if (parse_address(uid) in other_key.uids and
                        other_key.fingerprint[-16:] in cur_certs):
                    return True

            return False
Ejemplo n.º 10
0
    def expire(self, seckey, expiration_time='1y', passphrase=None):
        """
        Change expiration for C{key} key pair for the given C{expiration_time}
            period, from the current day.

        :param seckey: The secret key of the key pair to have the expiration
            time changed.
        :type seckey: OpenPGPKey
        :param expiration_time: new expiration time from the current day in
            'n', 'nw','nm' or 'ny' where n is a number
        :type expiration_time: str

        :return: The updated secret key, with new expiry date
        :rtype: OpenPGPKey

        :raise KeyExpirationError: Raised if failed to change expiration of key
            for some reason.
        """
        leap_assert_type(seckey, OpenPGPKey)
        leap_assert(seckey.private is True, 'Key is not private.')
        keys = [seckey]
        try:
            with TempGPGWrapper(keys, self._gpgbinary) as gpg:
                result = yield from_thread(gpg.expire,
                                           seckey.fingerprint,
                                           expiration_time=expiration_time,
                                           passphrase=passphrase)
                if result.status == 'ok':
                    for secret in [False, True]:
                        fetched_key = gpg.list_keys(secret=secret).pop()
                        key_data = gpg.export_keys(seckey.fingerprint,
                                                   secret=secret)
                        renewed_key = self._build_key_from_gpg(
                            fetched_key, key_data, seckey.address)
                        yield self.put_key(renewed_key)
                    defer.returnValue(renewed_key)
        except Exception as e:
            log.warn('Failed to change expiration of key: %s' % str(e))
            raise errors.KeyExpirationError(str(e))
Ejemplo n.º 11
0
    def verify(self, data, pubkey, detached_sig=None):
        """
        Verify signed C{data} with C{pubkey}, eventually using
        C{detached_sig}.

        :param data: The data to be verified.
        :type data: str
        :param pubkey: The public key to be used on verification.
        :type pubkey: OpenPGPKey
        :param detached_sig: A detached signature. If given, C{data} is
                             verified against this detached signature.
        :type detached_sig: str

        :return: signature matches
        :rtype: bool
        """
        leap_assert_type(pubkey, OpenPGPKey)
        leap_assert(pubkey.private is False)
        with TempGPGWrapper(pubkey, self._gpgbinary) as gpg:
            result = None
            if detached_sig is None:
                result = gpg.verify(data)
            else:
                # to verify using a detached sig we have to use
                # gpg.verify_file(), which receives the data as a binary
                # stream and the name of a file containing the signature.
                sf, sfname = tempfile.mkstemp()
                with os.fdopen(sf, 'w') as sfd:
                    sfd.write(detached_sig)
                result = gpg.verify_file(io.BytesIO(data), sig_file=sfname)
                os.unlink(sfname)
            gpgpubkey = gpg.list_keys().pop()
            valid = result.valid
            rfprint = result.fingerprint
            kfprint = gpgpubkey['fingerprint']
            return valid and rfprint == kfprint
Ejemplo n.º 12
0
def wrapper_init(tmpdir, benchmark, openpgp_keys, monkeypatch, _):
    pubkey = openpgp_keys[0]
    privkey = openpgp_keys[2]
    wrapper = TempGPGWrapper(keys=[pubkey, privkey])
    wrapper._build_keyring()
    return wrapper._gpg, pubkey, privkey
Ejemplo n.º 13
0
def wrapper_init_exec(fun, tmpdir, benchmark, openpgp_keys, monkeypatch, _):
    pubkey = openpgp_keys[0]
    privkey = openpgp_keys[2]
    wrapper = TempGPGWrapper(keys=[pubkey, privkey])
    wrapper._build_keyring()
    fun((wrapper._gpg, pubkey, privkey))
Ejemplo n.º 14
0
def wrapper_init_only(tmpdir, benchmark, openpgp_keys, monkeypatch, num_keys):
    keys = openpgp_keys[0:num_keys]
    wrapper = TempGPGWrapper(keys=keys)
    with wrapper as gpg:
        assert GPG == type(gpg)
Ejemplo n.º 15
0
def wrapper(keys=None):
    return TempGPGWrapper(keys=keys)