Exemple #1
0
def decrypt_bytes(data, **kwargs):
    r"""Decrypt ``data``.

    >>> b = '\n'.join([
    ...     '-----BEGIN PGP MESSAGE-----',
    ...     'Version: GnuPG v2.0.17 (GNU/Linux)',
    ...     '',
    ...     'hQEMA1Ea7aZDMrbjAQf/TAqLjksZSJxSqkBxYT5gtLQoXY6isvRZg2apjs7CW0y2',
    ...     'tFK/ptnVYAq2OtWQFhbiJXj8hmwJyyFfb3lghpeu4ihO52JgkkwOpmJb6dxjOi83',
    ...     'qDwaGOogEPH38BNLuwdrMCW0jmNROwvS796PtqSGUaJTuIiKUB8lETwPwIHrDc11',
    ...     'N3RWStE5uShNkXXQXplUoeCKf3N4XguXym+GQCqJQzlEMrkkDdr4l7mzvt3Nf8EA',
    ...     'SgSak086tUoo9x8IN5PJCuOJkcXcjQzFcpqOsA7dyZKO8NeQUZv2JvlZuorckNvN',
    ...     'xx3PwW0a8VeJgTQrh64ZK/d3F3gNHUTzXkq/UIn25tJFAcmSUwxtsBal7p8zAeCV',
    ...     '8zefsHRQ5Y03IBeYBcVJBhDS9XfvwLQTJiGGstPCxzKTwSUT1MzV5t5twG/STDCc',
    ...     'uxW3wSdo',
    ...     '=bZI+',
    ...     '-----END PGP MESSAGE-----',
    ...     ''
    ...     ]).encode('us-ascii')
    >>> decrypt_bytes(b)
    b'Success!\n'
    """
    input_read, input_write = _os.pipe()
    output_read, output_write = _os.pipe()
    client = get_client(**kwargs)
    try:
        hello(client)
        client.send_fds([input_read])
        client.make_request(_common.Request('INPUT', 'FD'))
        _os.close(input_read)
        input_read = -1
        client.send_fds([output_write])
        client.make_request(_common.Request('OUTPUT', 'FD'))
        _os.close(output_write)
        output_write = -1
        _write(input_write, data)
        _os.close(input_write)
        input_write = -1
        client.make_request(_common.Request('DECRYPT'))
        d = _read(output_read)
    finally:
        disconnect(client)
        for fd in [input_read, input_write, output_read, output_write]:
            if fd >= 0:
                _os.close(fd)
    return d
Exemple #2
0
def lookup_keys(patterns=None, **kwargs):
    """Lookup keys matching any patterns listed in ``patterns``.

    >>> import pprint

    >>> key = list(lookup_keys(['pgp-mime-test']))[0]
    >>> key
    <Key 4332B6E3>
    >>> key.subkeys
    [<SubKey 4332B6E3>, <SubKey 2F73DE2E>]
    >>> key.uids
    [<UserID pgp-mime-test>]
    >>> key.uids[0].uid
    'pgp-mime-test (http://blog.tremily.us/posts/pgp-mime/) <*****@*****.**>'
    >>> key.can_encrypt
    True
    >>> key.protocol
    'OpenPGP'

    >>> print(list(lookup_keys(['pgp-mime-test'])))
    [<Key 4332B6E3>]
    >>> print(list(lookup_keys(['*****@*****.**'])))
    [<Key 4332B6E3>]
    >>> print(list(lookup_keys(['4332B6E3'])))
    [<Key 4332B6E3>]
    >>> print(list(lookup_keys(['0x2F73DE2E'])))
    [<Key 4332B6E3>]
    >>> print(list(lookup_keys()))  # doctest: +ELLIPSIS
    [..., <Key 4332B6E3>, ...]
    """
    _LOG.debug('lookup key: {}'.format(patterns))
    client = _crypt.get_client(**kwargs)
    parameters = []
    if patterns:
        args = [' '.join(patterns)]
    else:
        args = []
    try:
        _crypt.hello(client)
        rs, result = client.make_request(_common.Request('KEYLIST', *args))
    finally:
        _crypt.disconnect(client)
    tag_mapping = {}
    tree = _etree.fromstring(result.replace(b'\x00', b''))
    for key in tree.findall('.//key'):
        k = Key()
        for child in key:
            attribute = tag_mapping.get(child.tag, child.tag.replace('-', '_'))
            if child.tag in [
                    'revoked', 'expired', 'disabled', 'invalid', 'can-encrypt',
                    'can-sign', 'can-certify', 'can-authenticate',
                    'is-qualified', 'secret', 'revoked'
            ]:
                # boolean values
                value = child.get('value')
                if not value.startswith('0x'):
                    raise NotImplementedError('{} value {}'.format(
                        child.tag, value))
                value = int(value, 16)
                value = bool(value)
            elif child.tag in ['protocol', 'owner-trust']:
                value = child.text
            elif child.tag in ['issuer', 'chain-id']:
                # ignore for now
                pass
            elif child.tag in ['subkeys', 'uids']:
                parser = globals()['_parse_{}'.format(attribute)]
                value = parser(child)
            else:
                raise NotImplementedError(child.tag)
            setattr(k, attribute, value)
        yield k
Exemple #3
0
def sign_and_encrypt_bytes(data,
                           signers=None,
                           recipients=None,
                           always_trust=False,
                           mode='detach',
                           allow_default_signer=False,
                           **kwargs):
    r"""Sign ``data`` with ``signers`` and encrypt to ``recipients``.

    Just sign (with a detached signature):

    >>> print(sign_and_encrypt_bytes(
    ...     bytes(b'Hello'), signers=['*****@*****.**']))
    ... # doctest: +ELLIPSIS
    b'-----BEGIN PGP SIGNATURE-----\n...-----END PGP SIGNATURE-----\n'

    Just encrypt:

    >>> sign_and_encrypt_bytes(
    ...     bytes(b'Hello'), recipients=['*****@*****.**'],
    ...     always_trust=True)
    ... # doctest: +ELLIPSIS
    b'-----BEGIN PGP MESSAGE-----\n...-----END PGP MESSAGE-----\n'

    Sign and encrypt:

    >>> sign_and_encrypt_bytes(
    ...     bytes(b'Hello'), signers=['*****@*****.**'],
    ...     recipients=['*****@*****.**'], always_trust=True)
    ... # doctest: +ELLIPSIS
    b'-----BEGIN PGP MESSAGE-----\n...-----END PGP MESSAGE-----\n'

    Sign and encrypt with a specific subkey:

    >>> sign_and_encrypt_bytes(
    ...     bytes(b'Hello'), signers=['0x2F73DE2E'],
    ...     recipients=['*****@*****.**'], always_trust=True)
    ... # doctest: +ELLIPSIS
    b'-----BEGIN PGP MESSAGE-----\n...-----END PGP MESSAGE-----\n'
    """
    input_read, input_write = _os.pipe()
    output_read, output_write = _os.pipe()
    client = get_client(**kwargs)
    try:
        hello(client)
        if signers:
            for signer in signers:
                client.make_request(_common.Request('SIGNER', signer))
        if recipients:
            for recipient in recipients:
                client.make_request(_common.Request('RECIPIENT', recipient))
        client.send_fds([input_read])
        client.make_request(_common.Request('INPUT', 'FD'))
        _os.close(input_read)
        input_read = -1
        client.send_fds([output_write])
        client.make_request(_common.Request('OUTPUT', 'FD'))
        _os.close(output_write)
        output_write = -1
        parameters = []
        if signers or allow_default_signer:
            if recipients:
                command = 'SIGN_ENCRYPT'
            else:
                command = 'SIGN'
                parameters.append('--{}'.format(mode))
        elif recipients:
            command = 'ENCRYPT'
        else:
            raise ValueError('must specify at least one signer or recipient')
        if always_trust:
            parameters.append('--always-trust')
        _write(input_write, data)
        _os.close(input_write)
        input_write = -1
        client.make_request(_common.Request(command, ' '.join(parameters)))
        d = _read(output_read)
    finally:
        disconnect(client)
        for fd in [input_read, input_write, output_read, output_write]:
            if fd >= 0:
                _os.close(fd)
    return d
Exemple #4
0
def hello(client):
    responses, data = client.get_responses()  # get initial 'OK' from server
    client.make_request(_common.Request('ARMOR', 'true'))
Exemple #5
0
def disconnect(client):
    client.make_request(_common.Request('BYE'))
    client.disconnect()
Exemple #6
0
def verify_bytes(data, signature=None, always_trust=False, **kwargs):
    r"""Verify a signature on ``data``, possibly decrypting first.

    These tests assume you didn't trust the distributed test key.

    >>> b = '\n'.join([
    ...     '-----BEGIN PGP MESSAGE-----',
    ...     'Version: GnuPG v2.0.17 (GNU/Linux)',
    ...     '',
    ...     'hQEMA1Ea7aZDMrbjAQf/YM1SeFzNGz0DnUynaEyhfGCvcqmjtbN1PtZMpT7VaQLN',
    ...     'a+c0faskr79Atz0+2IBR7CDOlcETrRtH2EnrWukbRIDtmffNFGuhMRTNfnQ15OIN',
    ...     'qrmt2P5gXznsgnm2XjzTK7S/Cc3Aq+zjaDrDt7bIedEdz+EyNgaKuL/lB9cAB8xL',
    ...     'YYp/yn55Myjair2idgzsa7w/QXdE3RhpyRLqR2Jgz4P1I1xOgUYnylbpIZL9FOKN',
    ...     'NR3RQhkGdANBku8otfthb5ZUGsNMV45ct4V8PE+xChjFb9gcwpaf1hhoIF/sYHD5',
    ...     'Bkf+v/J8F40KGYY16b0DjQIUlnra9y7q9jj0h2bvc9LAtgHtVUso133LLcVYl7RP',
    ...     'Vjyz9Ps366BtIdPlAL4CoF5hEcMKS5J3h1vRlyAKN4uHENl5vKvoxn7ID3JhhWQc',
    ...     '6QrPGis64zi3OnYor34HPh/KNJvkgOQkekmtYuTxnkiONA4lhMDJgeaVZ9WZq+GV',
    ...     'MaCvCFGNYU2TV4V8wMlnUbF8d5bDQ83g8MxIVKdDcnBzzYLZha+qmz4Spry9iB53',
    ...     'Sg/sM5H8gWWSl7Oj1lxVg7o7IscpQfVt6zL6jD2VjL3L3Hu7WEXIrcGZtvrP4d+C',
    ...     'TGYWiGlh5B2UCFk2bVctfw8W/QfaVvJYD4Rfqta2V2p14KIJLFRSGa1g26W4ixrH',
    ...     'XKxgaA3AIfJ+6c5RoisRLuYCxvQi91wkE9hAXR+inXK4Hq4SmiHoeITZFhHP3hh3',
    ...     'rbpp8mopiMNxWqCbuqgILP6pShn4oPclu9aR8uJ1ziDxISTGYC71mvLUERUjFn2L',
    ...     'fu6C0+TCC9RmeyL+eNdM6cjs1G7YR6yX',
    ...     '=phHd',
    ...     '-----END PGP MESSAGE-----',
    ...     '',
    ...     ]).encode('us-ascii')
    >>> output,verified,signatures = verify_bytes(b)
    >>> output
    b'Success!\n'
    >>> verified
    False
    >>> for s in signatures:
    ...     print(s.dumps())
    ... # doctest: +REPORT_UDIFF
    B2EDBE0E771A4B8708DD16A7511AEDA64332B6E3 signature:
      summary:
        CRL missing: False
        CRL too old: False
        bad policy: False
        green: False
        key expired: False
        key missing: False
        key revoked: False
        red: False
        signature expired: False
        system error: False
        valid: False
      status: success
      timestamp: Wed Mar 21 19:13:57 2012
      expiration timestamp: None
      wrong key usage: False
      pka trust: not available
      chain model: False
      validity: unknown
      validity reason: success
      public key algorithm: RSA
      hash algorithm: SHA256
    >>> b = b'Success!\n'
    >>> signature = '\n'.join([
    ...     '-----BEGIN PGP SIGNATURE-----',
    ...     'Version: GnuPG v2.0.17 (GNU/Linux)',
    ...     '',
    ...     'iQEcBAEBAgAGBQJPaiw/AAoJEFEa7aZDMrbj93gH/1fQPXLjUTpONJUTmvGoMLNA',
    ...     'W9ZhjpUL5i6rRqYGUvQ4kTEDuPMxkMrCyFCDHEhSDHufMek6Nso5/HeJn3aqxlgs',
    ...     'hmNlvAq4FI6JQyFL7eCp/XG9cPx1p42dTI7JAih8FuK21sS4m/H5XP3R/6KXC99D',
    ...     '39rrXCvvR+yNgKe2dxuJwmKuLteVlcWxiIQwVrYK70GtJHC5BO79G8yGccWoEy9C',
    ...     '9JkJiyNptqZyFjGBNmMmrCSFZ7ZFA02RB+laRmwuIiozw4TJYEksxPrgZMbbcFzx',
    ...     'zs3JHyV23+Fz1ftalvwskHE7tJkX9Ub8iBMNZ/KxJXXdPdpuMdEYVjoUehkQBQE=',
    ...     '=rRBP',
    ...     '-----END PGP SIGNATURE-----',
    ...     '',
    ...     ]).encode('us-ascii')
    >>> output,verified,signatures = verify_bytes(b, signature=signature)
    >>> output
    b'Success!\n'
    >>> verified
    False
    >>> for s in signatures:
    ...     print(s.dumps())
    ... # doctest: +REPORT_UDIFF
    B2EDBE0E771A4B8708DD16A7511AEDA64332B6E3 signature:
      summary:
        CRL missing: False
        CRL too old: False
        bad policy: False
        green: False
        key expired: False
        key missing: False
        key revoked: False
        red: False
        signature expired: False
        system error: False
        valid: False
      status: success
      timestamp: Wed Mar 21 19:30:07 2012
      expiration timestamp: None
      wrong key usage: False
      pka trust: not available
      chain model: False
      validity: unknown
      validity reason: success
      public key algorithm: RSA
      hash algorithm: SHA1

    Data signed by a subkey returns the subkey fingerprint.  To find
    the primary key for a given subkey, use
    ``pgp_mime.key.lookup_keys()``.

    >>> b = '\n'.join([
    ...     '-----BEGIN PGP MESSAGE-----',
    ...     'Version: GnuPG v2.0.19 (GNU/Linux)',
    ...     '',
    ...     'hQEMAxcQCLovc94uAQf9ErTZnr0lYRlLLZIk1VcpNNTHrMro+BmqpFC0jprA4/2m',
    ...     '92klBF4TIS1A9bU5oxzQquaAIDV42P3sXrbxu/YhHLmPGH+dc2JVSfPLL0XOL5GC',
    ...     'qpQYe5lglRBReFSRktrfhukjHBoXvh3c8T4xYK2r+nIV4gsp+FrSQMIOdhhBoC36',
    ...     'U1MOk+R+I0JDbWdzZzJONs7ZcAcNDVKqxmAXZUqVgkhPpnGBSBuF9ExKRT3S6e5N',
    ...     'Rsorb/DjGIUHSZuH2EaWAUz1jJ3nSta7TnveT/avfJiAV7cRS4oVgyyFyuHO5gkI',
    ...     'o0obeJaut3enVgpq2TUUk0M4L8TX4jjKvDGAYNyuPNLAsQFHLj5eLmJSudGStWuA',
    ...     'WjKLqBHD0M8/OcwnrTMleJl+h50ZsHO1tvvkXelH+w/jD5SMS+ktxq2Te8Vj7BmM',
    ...     '0WQn3Ys7ViA5PgcSpbqNNLdgc1EMcpPI/sfJAORPKVWRPBKDXX/irY2onAMSe5gH',
    ...     'teNX6bZd/gaoLWqD/1ZhsOCnlV7LY1R929TJ9vxnJcfKKAKwBDfAaSbecUUMECVw',
    ...     's4u3ZT1pmNslBmH6XSy3ifLYWu/2xsJuhPradT88BJOBARMGg81gOE6zxGRrMLJa',
    ...     'KojFgqaF2y4nlZAyaJ1Ld4qCaoQogaL9qE1BbmgtBehZ2FNQiIBSLC0fUUl8A4Py',
    ...     '4d9ZxUoSp7nZmgTN5pUH1N9DIC4ntp/Rak2WnpS7+dRPlp9A2SF0RkeLY+JD9gNm',
    ...     'j44zBkI79KlgaE/cMt6xUXAF/1ZR/Hv/6GUazGx0l23CnSGuqzLpex2uKOxfKiJt',
    ...     'jfgyZRhIdFJnRuEXt8dTTDiiYA==',
    ...     '=0o+x',
    ...     '-----END PGP MESSAGE-----',
    ...     '',
    ...     ]).encode('us-ascii')
    >>> output,verified,signatures = verify_bytes(b)
    >>> output
    b'Hello'
    >>> verified
    False
    >>> for s in signatures:
    ...     print(s.dumps())
    ... # doctest: +REPORT_UDIFF
    DECC812C8795ADD60538B0CD171008BA2F73DE2E signature:
      summary:
        CRL missing: False
        CRL too old: False
        bad policy: False
        green: False
        key expired: False
        key missing: False
        key revoked: False
        red: False
        signature expired: False
        system error: False
        valid: False
      status: success
      timestamp: Thu Sep 20 15:29:28 2012
      expiration timestamp: None
      wrong key usage: False
      pka trust: not available
      chain model: False
      validity: unknown
      validity reason: success
      public key algorithm: RSA
      hash algorithm: SHA256
    """
    input_read, input_write = _os.pipe()
    if signature:
        message_read, message_write = _os.pipe()
        output_read = output_write = -1
    else:
        message_read = message_write = -1
        output_read, output_write = _os.pipe()
    client = get_client(**kwargs)
    verified = None
    signatures = []
    try:
        hello(client)
        client.send_fds([input_read])
        client.make_request(_common.Request('INPUT', 'FD'))
        _os.close(input_read)
        input_read = -1
        if signature:
            client.send_fds([message_read])
            client.make_request(_common.Request('MESSAGE', 'FD'))
            _os.close(message_read)
            message_read = -1
        else:
            client.send_fds([output_write])
            client.make_request(_common.Request('OUTPUT', 'FD'))
            _os.close(output_write)
            output_write = -1
        if signature:
            _write(input_write, signature)
            _os.close(input_write)
            input_write = -1
            _write(message_write, data)
            _os.close(message_write)
            message_write = -1
        else:
            _write(input_write, data)
            _os.close(input_write)
            input_write = -1
        client.make_request(_common.Request('VERIFY'))
        if signature:
            plain = data
        else:
            plain = _read(output_read)
        rs, result = client.make_request(_common.Request('RESULT'))
        signatures = list(_signature.verify_result_signatures(result))
        verified = True
        for signature in signatures:
            if signature.status != 'success':
                verified = False
            elif signature.pka_trust != 'good':
                verified = False
    finally:
        disconnect(client)
        for fd in [
                input_read, input_write, message_read, message_write,
                output_read, output_write
        ]:
            if fd >= 0:
                _os.close(fd)
    return (plain, verified, signatures)
Exemple #7
0
        help='increase verbosity')
    parser.add_argument(
        'filename',
        help="path to server's unix socket")

    args = parser.parse_args()

    client = _client.AssuanClient(name='get-info', close_on_disconnect=True)

    if args.verbose:
        client.logger.setLevel(max(
                logging.DEBUG, client.logger.level - 10*args.verbose))

    client.connect(socket_path=args.filename)
    try:
        response = client.read_response()
        assert response.type == 'OK', response
        client.make_request(_common.Request('HELP'))
        client.make_request(_common.Request('HELP GETINFO'))
        for attribute in ['version', 'pid', 'socket_name', 'ssh_socket_name']:
            try:
                client.make_request(_common.Request('GETINFO', attribute))
            except _error.AssuanError as e:
                if e.message.startswith('No data'):
                    pass
                else:
                    raise
    finally:
        client.make_request(_common.Request('BYE'))
        client.disconnect()