diff options
| -rw-r--r-- | src/leap/common/keymanager/errors.py | 28 | ||||
| -rw-r--r-- | src/leap/common/keymanager/openpgp.py | 279 | ||||
| -rw-r--r-- | src/leap/common/tests/test_keymanager.py | 246 | 
3 files changed, 427 insertions, 126 deletions
| diff --git a/src/leap/common/keymanager/errors.py b/src/leap/common/keymanager/errors.py index 1cf506e..f712975 100644 --- a/src/leap/common/keymanager/errors.py +++ b/src/leap/common/keymanager/errors.py @@ -25,12 +25,14 @@ class KeyNotFound(Exception):      """      Raised when key was no found on keyserver.      """ +    pass  class KeyAlreadyExists(Exception):      """      Raised when attempted to create a key that already exists.      """ +    pass  class KeyAttributesDiffer(Exception): @@ -38,9 +40,35 @@ class KeyAttributesDiffer(Exception):      Raised when trying to delete a key but the stored key differs from the key      passed to the delete_key() method.      """ +    pass  class NoPasswordGiven(Exception):      """      Raised when trying to perform some action that needs a password without      providing one.      """ +    pass + +class InvalidSignature(Exception): +    """ +    Raised when signature could not be verified. +    """ +    pass + +class EncryptionFailed(Exception): +    """ +    Raised upon failures of encryption. +    """ +    pass + +class DecryptionFailed(Exception): +    """ +    Raised upon failures of decryption. +    """ +    pass + +class SignFailed(Exception): +    """ +    Raised when failed to sign. +    """ +    pass diff --git a/src/leap/common/keymanager/openpgp.py b/src/leap/common/keymanager/openpgp.py index 0fd314a..0cb1308 100644 --- a/src/leap/common/keymanager/openpgp.py +++ b/src/leap/common/keymanager/openpgp.py @@ -29,7 +29,11 @@ from leap.common.check import leap_assert, leap_assert_type  from leap.common.keymanager.errors import (      KeyNotFound,      KeyAlreadyExists, -    KeyAttributesDiffer +    KeyAttributesDiffer, +    InvalidSignature, +    EncryptionFailed, +    DecryptionFailed, +    SignFailed,  )  from leap.common.keymanager.keys import (      EncryptionKey, @@ -45,84 +49,163 @@ from leap.common.keymanager.gpg import GPGWrapper  # API functions  # -def encrypt_sym(data, passphrase): +def encrypt_sym(data, passphrase, sign=None):      """ -    Encrypt C{data} with C{passphrase}. +    Encrypt C{data} with C{passphrase} and sign with C{sign} private key.      @param data: The data to be encrypted.      @type data: str      @param passphrase: The passphrase used to encrypt C{data}.      @type passphrase: str +    @param sign: The private key used for signing. +    @type sign: OpenPGPKey      @return: The encrypted data.      @rtype: str      """ +    leap_assert_type(passphrase, str) +    if sign is not None: +        leap_assert_type(sign, OpenPGPKey) +        leap_assert(sign.private == True)      def _encrypt_cb(gpg): -        return gpg.encrypt( -                data, None, passphrase=passphrase, symmetric=True).data - -    return _safe_call(_encrypt_cb) - - -def decrypt_sym(data, passphrase): +        result = gpg.encrypt( +            data, None, +            sign=sign.key_id if sign else None, +            passphrase=passphrase, symmetric=True) +        # 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 +        if result.ok is False: +            raise EncryptionFailed('Failed to encrypt: %s' % result.stderr) +        return result.data + +    return _safe_call(_encrypt_cb, [sign]) + + +def decrypt_sym(data, passphrase, verify=None):      """ -    Decrypt C{data} with C{passphrase}. +    Decrypt C{data} with C{passphrase} and verify with C{verify} public +    key.      @param data: The data to be decrypted.      @type data: str      @param passphrase: The passphrase used to decrypt C{data}.      @type passphrase: str +    @param verify: The key used to verify a signature. +    @type verify: OpenPGPKey      @return: The decrypted data.      @rtype: str + +    @raise InvalidSignature: Raised if unable to verify the signature with +        C{verify} key.      """ +    leap_assert_type(passphrase, str) +    if verify is not None: +        leap_assert_type(verify, OpenPGPKey) +        leap_assert(verify.private == False)      def _decrypt_cb(gpg): -        return gpg.decrypt(data, passphrase=passphrase).data - -    return _safe_call(_decrypt_cb) - - -def encrypt_asym(data, key): +        result = gpg.decrypt(data, passphrase=passphrase) +        # result.ok    - (bool) indicates if the operation succeeded +        # result.valid - (bool) indicates if the signature was verified +        # result.data  - (bool) contains the result of the operation +        # result.pubkey_fingerpring  - (str) contains the fingerprint of the +        #                              public key that signed this data. +        if result.ok is False: +            raise DecryptionFailed('Failed to decrypt: %s', result.stderr) +        if verify is not None: +            if result.valid is False or \ +                    verify.fingerprint != result.pubkey_fingerprint: +                raise InvalidSignature( +                    'Failed to verify signature with key %s: %s' % +                    (verify.key_id, result.stderr)) +        return result.data + +    return _safe_call(_decrypt_cb, [verify]) + + +def encrypt_asym(data, pubkey, sign=None):      """ -    Encrypt C{data} using public @{key}. +    Encrypt C{data} using public @{key} and sign with C{sign} key.      @param data: The data to be encrypted.      @type data: str -    @param key: The key used to encrypt. -    @type key: OpenPGPKey +    @param pubkey: The key used to encrypt. +    @type pubkey: OpenPGPKey +    @param sign: The key used for signing. +    @type sign: OpenPGPKey      @return: The encrypted data.      @rtype: str      """ -    leap_assert(key.private is False, 'Key is not public.') +    leap_assert_type(pubkey, OpenPGPKey) +    leap_assert(pubkey.private is False, 'Key is not public.') +    if sign is not None: +        leap_assert_type(sign, OpenPGPKey) +        leap_assert(sign.private == True)      def _encrypt_cb(gpg): -        return gpg.encrypt( -                data, key.fingerprint, symmetric=False).data - -    return _safe_call(_encrypt_cb, key.key_data) - - -def decrypt_asym(data, key): +        result = gpg.encrypt( +            data, pubkey.fingerprint, +            sign=sign.key_id if sign else None, +            symmetric=False) +        # 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 +        if result.ok is False: +            raise EncryptionFailed( +                'Failed to encrypt with key %s: %s' % +                (pubkey.key_id, result.stderr)) +        return result.data + +    return _safe_call(_encrypt_cb, [pubkey, sign]) + + +def decrypt_asym(data, privkey, verify=None):      """ -    Decrypt C{data} using private @{key}. +    Decrypt C{data} using private @{key} and verify with C{verify} key.      @param data: The data to be decrypted.      @type data: str -    @param key: The key used to decrypt. -    @type key: OpenPGPKey +    @param privkey: The key used to decrypt. +    @type privkey: OpenPGPKey +    @param verify: The key used to verify a signature. +    @type verify: OpenPGPKey      @return: The decrypted data.      @rtype: str + +    @raise InvalidSignature: Raised if unable to verify the signature with +        C{verify} key.      """ -    leap_assert(key.private is True, 'Key is not private.') +    leap_assert(privkey.private is True, 'Key is not private.') +    if verify is not None: +        leap_assert_type(verify, OpenPGPKey) +        leap_assert(verify.private == False)      def _decrypt_cb(gpg): -        return gpg.decrypt(data).data - -    return _safe_call(_decrypt_cb, key.key_data) +        result = gpg.decrypt(data) +        # result.ok    - (bool) indicates if the operation succeeded +        # result.valid - (bool) indicates if the signature was verified +        # result.data  - (bool) contains the result of the operation +        # result.pubkey_fingerpring  - (str) contains the fingerprint of the +        #                              public key that signed this data. +        if result.ok is False: +            raise DecryptionFailed('Failed to decrypt with key %s: %s' % +                                   (privkey.key_id, result.stderr)) +        if verify is not None: +            if result.valid is False or \ +                    verify.fingerprint != result.pubkey_fingerprint: +                raise InvalidSignature( +                    'Failed to verify signature with key %s: %s' % +                    (verify.key_id, result.stderr)) +        return result.data + +    return _safe_call(_decrypt_cb, [privkey, verify])  def is_encrypted(data): @@ -175,45 +258,61 @@ def is_encrypted_asym(data):      return _safe_call(_is_encrypted_cb) -def sign(data, key): +def sign(data, privkey):      """ -    Sign C{data} with C{key}. +    Sign C{data} with C{privkey}.      @param data: The data to be signed.      @type data: str -    @param key: The key to be used to sign. -    @type key: OpenPGPKey +    @param privkey: The private key to be used to sign. +    @type privkey: OpenPGPKey      @return: The ascii-armored signed data.      @rtype: str      """ -    leap_assert_type(key, OpenPGPKey) -    leap_assert(key.private == True) +    leap_assert_type(privkey, OpenPGPKey) +    leap_assert(privkey.private == True)      def _sign_cb(gpg): -        return gpg.sign(data, keyid=key.key_id).data +        result = gpg.sign(data, keyid=privkey.key_id) +        # result.fingerprint - contains the fingerprint of the key used to +        #                      sign. +        if result.fingerprint is None: +            raise SignFailed( +                'Failed to sign with key %s: %s' % +                (privkey.key_id, result.stderr)) +        leap_assert( +            result.fingerprint == privkey.fingerprint, +            'Signature and private key fingerprints mismatch: %s != %s' % +            (result.fingerprint, privkey.fingerprint)) +        return result.data -    return _safe_call(_sign_cb, key.key_data) +    return _safe_call(_sign_cb, [privkey]) -def verify(data, key): +def verify(data, pubkey):      """ -    Verify signed C{data} with C{key}. +    Verify signed C{data} with C{pubkey}.      @param data: The data to be verified.      @type data: str -    @param key: The key to be used on verification. -    @type key: OpenPGPKey +    @param pubkey: The public key to be used on verification. +    @type pubkey: OpenPGPKey      @return: The ascii-armored signed data.      @rtype: str      """ -    leap_assert_type(key, OpenPGPKey) -    leap_assert(key.private == False) +    leap_assert_type(pubkey, OpenPGPKey) +    leap_assert(pubkey.private == False)      def _verify_cb(gpg): -        return gpg.verify(data).valid +        result = gpg.verify(data) +        if result.valid is False or \ +                result.fingerprint != pubkey.fingerprint: +            raise InvalidSignature( +                'Failed to verify signature with key %s.' % pubkey.key_id) +        return True -    return _safe_call(_verify_cb, key.key_data) +    return _safe_call(_verify_cb, [pubkey])  #  # Helper functions @@ -248,35 +347,48 @@ def _build_key_from_gpg(address, key, key_data):      ) -def _build_unitary_gpgwrapper(key_data=None): +def _build_keyring(keys=[]):      """ -    Return a temporary GPG wrapper keyring containing exactly zero or one -    keys. -    Temporary unitary keyrings allow the to use GPG's facilities for exactly -    one key. This function creates an empty temporary keyring and imports -    C{key_data} if it is not None. +    Create an empty GPG keyring and import C{keys} into it. + +    @param keys: List of keys to add to the keyring. +    @type keys: list of OpenPGPKey -    @param key_data: ASCII armored key data. -    @type key_data: str      @return: A GPG wrapper with a unitary keyring.      @rtype: gnupg.GPG      """ +    privkeys = filter(lambda key: key.private == True, keys) +    pubkeys = filter(lambda key: key.private == False, keys) +    # here we filter out public keys that have a correspondent private key in +    # the list because the private key_data by itself is enough to also have +    # the public key in the keyring, and we want to count the keys afterwards. +    privaddrs = map(lambda privkey: privkey.address, privkeys) +    pubkeys = filter(lambda pubkey: pubkey.address not in privaddrs, pubkeys) +    # create temporary dir for temporary gpg keyring      tmpdir = tempfile.mkdtemp()      gpg = GPGWrapper(gnupghome=tmpdir)      leap_assert(len(gpg.list_keys()) is 0, 'Keyring not empty.') -    if key_data: -        gpg.import_keys(key_data) -        leap_assert( -            len(gpg.list_keys()) is 1, -            'Unitary keyring has wrong number of keys: %d.' -            % len(gpg.list_keys())) +    # import keys into the keyring +    gpg.import_keys( +        reduce( +            lambda x, y: x+y, +            [key.key_data for key in pubkeys+privkeys], '')) +    # assert the number of keys in the keyring +    leap_assert( +        len(gpg.list_keys()) == len(pubkeys)+len(privkeys), +        'Wrong number of public keys in keyring: %d, should be %d)' % +        (len(gpg.list_keys()), len(pubkeys)+len(privkeys))) +    leap_assert( +        len(gpg.list_keys(secret=True)) == len(privkeys), +        'Wrong number of private keys in keyring: %d, should be %d)' % +        (len(gpg.list_keys(secret=True)), len(privkeys)))      return gpg -def _destroy_unitary_gpgwrapper(gpg): +def _destroy_keyring(gpg):      """ -    Securely erase a unitary keyring. +    Securely erase a keyring.      @param gpg: A GPG wrapper instance.      @type gpg: gnupg.GPG @@ -292,23 +404,21 @@ def _destroy_unitary_gpgwrapper(gpg):      shutil.rmtree(gpg.gnupghome) -def _safe_call(callback, key_data=None, **kwargs): +def _safe_call(callback, keys=[]):      """ -    Run C{callback} in an unitary keyring containing C{key_data}. +    Run C{callback} over a keyring containing C{keys}.      @param callback: Function whose first argument is the gpg keyring.      @type callback: function(gnupg.GPG) -    @param key_data: ASCII armored key data. -    @type key_data: str -    @param **kwargs: Other eventual parameters for the callback. -    @type **kwargs: **dict +    @param keys: List of keys to add to the keyring. +    @type keys: list of OpenPGPKey      @return: The results of the callback.      @rtype: str or bool      """ -    gpg = _build_unitary_gpgwrapper(key_data) -    val = callback(gpg, **kwargs) -    _destroy_unitary_gpgwrapper(gpg) +    gpg = _build_keyring(filter(lambda key: key is not None, keys)) +    val = callback(gpg) +    _destroy_keyring(gpg)      return val @@ -404,18 +514,17 @@ class OpenPGPScheme(EncryptionScheme):              raise KeyNotFound(address)          return build_key_from_dict(OpenPGPKey, address, doc.content) -    def put_key_raw(self, data): +    def put_ascii_key(self, key_data):          """ -        Put key contained in raw C{data} in local storage. +        Put key contained in ascii-armored C{key_data} in local storage. -        @param data: The key data to be stored. -        @type data: str +        @param key_data: The key data to be stored. +        @type key_data: str          """ -        # TODO: add more checks for correct key data. -        leap_assert(data is not None, 'Data does not represent a key.') - -        def _put_key_raw_cb(gpg): +        leap_assert_type(key_data, str) +        def _put_ascii_key_cb(gpg): +            gpg.import_keys(key_data)              privkey = None              pubkey = None              try: @@ -449,7 +558,7 @@ class OpenPGPScheme(EncryptionScheme):                  gpg.export_keys(pubkey['fingerprint'], secret=False))              self.put_key(openpgp_pubkey) -        _safe_call(_put_key_raw_cb, data) +        _safe_call(_put_ascii_key_cb)      def put_key(self, key):          """ diff --git a/src/leap/common/tests/test_keymanager.py b/src/leap/common/tests/test_keymanager.py index d3dee40..e52766a 100644 --- a/src/leap/common/tests/test_keymanager.py +++ b/src/leap/common/tests/test_keymanager.py @@ -51,6 +51,7 @@ from leap.common.keymanager import errors  ADDRESS = 'leap@leap.se' +ADDRESS_2 = 'anotheruser@leap.se'  class KeyManagerUtilTestCase(BaseLeapTest): @@ -182,15 +183,15 @@ class OpenPGPCryptoTestCase(KeyManagerWithSoledadTestCase):      def test_openpgp_put_delete_key(self):          pgp = openpgp.OpenPGPScheme(self._soledad)          self.assertRaises(KeyNotFound, pgp.get_key, ADDRESS) -        pgp.put_key_raw(PUBLIC_KEY) +        pgp.put_ascii_key(PUBLIC_KEY)          key = pgp.get_key(ADDRESS, private=False)          pgp.delete_key(key)          self.assertRaises(KeyNotFound, pgp.get_key, ADDRESS) -    def test_openpgp_put_key_raw(self): +    def test_openpgp_put_ascii_key(self):          pgp = openpgp.OpenPGPScheme(self._soledad)          self.assertRaises(KeyNotFound, pgp.get_key, ADDRESS) -        pgp.put_key_raw(PUBLIC_KEY) +        pgp.put_ascii_key(PUBLIC_KEY)          key = pgp.get_key(ADDRESS, private=False)          self.assertIsInstance(key, openpgp.OpenPGPKey)          self.assertEqual( @@ -203,7 +204,7 @@ class OpenPGPCryptoTestCase(KeyManagerWithSoledadTestCase):      def test_get_public_key(self):          pgp = openpgp.OpenPGPScheme(self._soledad)          self.assertRaises(KeyNotFound, pgp.get_key, ADDRESS) -        pgp.put_key_raw(PUBLIC_KEY) +        pgp.put_ascii_key(PUBLIC_KEY)          self.assertRaises(              KeyNotFound, pgp.get_key, ADDRESS, private=True)          key = pgp.get_key(ADDRESS, private=False) @@ -216,7 +217,7 @@ class OpenPGPCryptoTestCase(KeyManagerWithSoledadTestCase):      def test_openpgp_encrypt_decrypt_asym(self):          # encrypt          pgp = openpgp.OpenPGPScheme(self._soledad) -        pgp.put_key_raw(PUBLIC_KEY) +        pgp.put_ascii_key(PUBLIC_KEY)          pubkey = pgp.get_key(ADDRESS, private=False)          cyphertext = openpgp.encrypt_asym('data', pubkey)          # assert @@ -229,7 +230,7 @@ class OpenPGPCryptoTestCase(KeyManagerWithSoledadTestCase):          # decrypt          self.assertRaises(              KeyNotFound, pgp.get_key, ADDRESS, private=True) -        pgp.put_key_raw(PRIVATE_KEY) +        pgp.put_ascii_key(PRIVATE_KEY)          privkey = pgp.get_key(ADDRESS, private=True)          plaintext = openpgp.decrypt_asym(cyphertext, privkey)          pgp.delete_key(pubkey) @@ -250,13 +251,146 @@ class OpenPGPCryptoTestCase(KeyManagerWithSoledadTestCase):          plaintext = openpgp.decrypt_sym(cyphertext, 'pass')          self.assertEqual('data', plaintext) +    def test_verify_with_private_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        signed = openpgp.sign(data, privkey) +        self.assertRaises( +            AssertionError, +            openpgp.verify, signed, privkey) + +    def test_sign_with_public_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PUBLIC_KEY) +        data = 'data' +        pubkey = pgp.get_key(ADDRESS, private=False) +        self.assertRaises( +            AssertionError, +            openpgp.sign, data, pubkey) + +    def test_verify_with_wrong_key_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        signed = openpgp.sign(data, privkey) +        pgp.put_ascii_key(PUBLIC_KEY_2) +        wrongkey = pgp.get_key(ADDRESS_2) +        self.assertRaises( +            errors.InvalidSignature, +            openpgp.verify, signed, wrongkey) + +    def test_encrypt_asym_sign_with_public_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        pubkey = pgp.get_key(ADDRESS, private=False) +        self.assertRaises( +            AssertionError, +            openpgp.encrypt_asym, data, privkey, sign=pubkey) + +    def test_encrypt_sym_sign_with_public_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PUBLIC_KEY) +        data = 'data' +        pubkey = pgp.get_key(ADDRESS, private=False) +        self.assertRaises( +            AssertionError, +            openpgp.encrypt_sym, data, '123', sign=pubkey) + +    def test_decrypt_asym_verify_with_private_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        pubkey = pgp.get_key(ADDRESS, private=False) +        encrypted_and_signed = openpgp.encrypt_asym( +            data, pubkey, sign=privkey) +        self.assertRaises( +            AssertionError, +            openpgp.decrypt_asym, +            encrypted_and_signed, privkey, verify=privkey) + +    def test_decrypt_asym_verify_with_wrong_key_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        pubkey = pgp.get_key(ADDRESS, private=False) +        encrypted_and_signed = openpgp.encrypt_asym(data, pubkey, sign=privkey) +        pgp.put_ascii_key(PUBLIC_KEY_2) +        wrongkey = pgp.get_key('anotheruser@leap.se') +        self.assertRaises( +            errors.InvalidSignature, +            openpgp.verify, encrypted_and_signed, wrongkey) + +    def test_decrypt_sym_verify_with_private_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        encrypted_and_signed = openpgp.encrypt_sym(data, '123', sign=privkey) +        self.assertRaises( +            AssertionError, +            openpgp.decrypt_sym, +            encrypted_and_signed, 'decrypt', verify=privkey) + +    def test_decrypt_sym_verify_with_private_raises(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        encrypted_and_signed = openpgp.encrypt_sym(data, '123', sign=privkey) +        pgp.put_ascii_key(PUBLIC_KEY_2) +        wrongkey = pgp.get_key('anotheruser@leap.se') +        self.assertRaises( +            errors.InvalidSignature, +            openpgp.verify, encrypted_and_signed, wrongkey) + +    def test_sign_verify(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        signed = openpgp.sign(data, privkey) +        pubkey = pgp.get_key(ADDRESS, private=False) +        self.assertTrue(openpgp.verify(signed, pubkey)) + +    def test_encrypt_asym_sign_decrypt_verify(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        pubkey = pgp.get_key(ADDRESS, private=False) +        privkey = pgp.get_key(ADDRESS, private=True) +        pgp.put_ascii_key(PRIVATE_KEY_2) +        pubkey2 = pgp.get_key(ADDRESS_2, private=False) +        privkey2 = pgp.get_key(ADDRESS_2, private=True) +        data = 'data' +        encrypted_and_signed = openpgp.encrypt_asym(data, pubkey2, sign=privkey) +        res = openpgp.decrypt_asym( +                encrypted_and_signed, privkey2, verify=pubkey) +        self.assertTrue(data, res) + +    def test_encrypt_sym_sign_decrypt_verify(self): +        pgp = openpgp.OpenPGPScheme(self._soledad) +        pgp.put_ascii_key(PRIVATE_KEY) +        data = 'data' +        privkey = pgp.get_key(ADDRESS, private=True) +        pubkey = pgp.get_key(ADDRESS, private=False) +        encrypted_and_signed = openpgp.encrypt_sym(data, '123', sign=privkey) +        res = openpgp.decrypt_sym( +                encrypted_and_signed, '123', verify=pubkey) +        self.assertEqual(data, res) +  class KeyManagerKeyManagementTestCase(      KeyManagerWithSoledadTestCase):      def test_get_all_keys_in_db(self):          km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PRIVATE_KEY) +        km._wrapper_map[OpenPGPKey].put_ascii_key(PRIVATE_KEY)          # get public keys          keys = km.get_all_keys_in_local_db(False)          self.assertEqual(len(keys), 1, 'Wrong number of keys') @@ -270,7 +404,7 @@ class KeyManagerKeyManagementTestCase(      def test_get_public_key(self):          km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PRIVATE_KEY) +        km._wrapper_map[OpenPGPKey].put_ascii_key(PRIVATE_KEY)          # get the key          key = km.get_key(ADDRESS, OpenPGPKey, private=False,                           fetch_remote=False) @@ -282,7 +416,7 @@ class KeyManagerKeyManagementTestCase(      def test_get_private_key(self):          km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PRIVATE_KEY) +        km._wrapper_map[OpenPGPKey].put_ascii_key(PRIVATE_KEY)          # get the key          key = km.get_key(ADDRESS, OpenPGPKey, private=True,                           fetch_remote=False) @@ -300,7 +434,7 @@ class KeyManagerKeyManagementTestCase(      def test_send_private_key_raises_key_not_found(self):          km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PUBLIC_KEY) +        km._wrapper_map[OpenPGPKey].put_ascii_key(PUBLIC_KEY)          self.assertRaises(              KeyNotFound,              km.send_key, OpenPGPKey, send_private=True, @@ -308,14 +442,14 @@ class KeyManagerKeyManagementTestCase(      def test_send_private_key_without_password_raises(self):          km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PUBLIC_KEY) +        km._wrapper_map[OpenPGPKey].put_ascii_key(PUBLIC_KEY)          self.assertRaises(              NoPasswordGiven,              km.send_key, OpenPGPKey, send_private=True)      def test_send_public_key(self):          km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PUBLIC_KEY) +        km._wrapper_map[OpenPGPKey].put_ascii_key(PUBLIC_KEY)          km._fetcher.put = mock.Mock()          km.token = '123'          km.send_key(OpenPGPKey, send_private=False) @@ -356,41 +490,13 @@ class KeyManagerKeyManagementTestCase(      def test_refresh_keys(self):          # TODO: maybe we should not attempt to refresh our own public key?          km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PUBLIC_KEY) +        km._wrapper_map[OpenPGPKey].put_ascii_key(PUBLIC_KEY)          km.fetch_keys_from_server = mock.Mock(return_value=[])          km.refresh_keys()          km.fetch_keys_from_server.assert_called_once_with(              'leap@leap.se'          ) -    def test_verify_with_private_raises(self): -        km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PRIVATE_KEY) -        data = 'data' -        privkey = km.get_key(ADDRESS, OpenPGPKey, private=True) -        signed = openpgp.sign(data, privkey) -        self.assertRaises( -            AssertionError, -            openpgp.verify, signed, privkey) - -    def test_sign_with_public_raises(self): -        km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PUBLIC_KEY) -        data = 'data' -        pubkey = km.get_key(ADDRESS, OpenPGPKey, private=False) -        self.assertRaises( -            AssertionError, -            openpgp.sign, data, pubkey) - -    def test_sign_verify(self): -        km = self._key_manager() -        km._wrapper_map[OpenPGPKey].put_key_raw(PRIVATE_KEY) -        data = 'data' -        privkey = km.get_key(ADDRESS, OpenPGPKey, private=True) -        signed = openpgp.sign(data, privkey) -        pubkey = km.get_key(ADDRESS, OpenPGPKey, private=False) -        self.assertTrue(openpgp.verify(signed, pubkey)) -  # Key material for testing  KEY_FINGERPRINT = "E36E738D69173C13D709E44F2F455E2824D18DDF" @@ -554,3 +660,61 @@ RZXoH+FTg9UAW87eqU610npOkT6cRaBxaMK/mDtGNdc=  =JTFu  -----END PGP PRIVATE KEY BLOCK-----  """ + +PUBLIC_KEY_2 = """ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +mI0EUYwJXgEEAMbTKHuPJ5/Gk34l9Z06f+0WCXTDXdte1UBoDtZ1erAbudgC4MOR +gquKqoj3Hhw0/ILqJ88GcOJmKK/bEoIAuKaqlzDF7UAYpOsPZZYmtRfPC2pTCnXq +Z1vdeqLwTbUspqXflkCkFtfhGKMq5rH8GV5a3tXZkRWZhdNwhVXZagC3ABEBAAG0 +IWFub3RoZXJ1c2VyIDxhbm90aGVydXNlckBsZWFwLnNlPoi4BBMBAgAiBQJRjAle +AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRB/nfpof+5XWotuA/4tLN4E +gUr7IfLy2HkHAxzw7A4rqfMN92DIM9mZrDGaWRrOn3aVF7VU1UG7MDkHfPvp/cFw +ezoCw4s4IoHVc/pVlOkcHSyt4/Rfh248tYEJmFCJXGHpkK83VIKYJAithNccJ6Q4 +JE/o06Mtf4uh/cA1HUL4a4ceqUhtpLJULLeKo7iNBFGMCV4BBADsyQI7GR0wSAxz +VayLjuPzgT+bjbFeymIhjuxKIEwnIKwYkovztW+4bbOcQs785k3Lp6RzvigTpQQt +Z/hwcLOqZbZw8t/24+D+Pq9mMP2uUvCFFqLlVvA6D3vKSQ/XNN+YB919WQ04jh63 +yuRe94WenT1RJd6xU1aaUff4rKizuQARAQABiJ8EGAECAAkFAlGMCV4CGwwACgkQ +f536aH/uV1rPZQQAqCzRysOlu8ez7PuiBD4SebgRqWlxa1TF1ujzfLmuPivROZ2X +Kw5aQstxgGSjoB7tac49s0huh4X8XK+BtJBfU84JS8Jc2satlfwoyZ35LH6sDZck +I+RS/3we6zpMfHs3vvp9xgca6ZupQxivGtxlJs294TpJorx+mFFqbV17AzQ= +=Thdu +-----END PGP PUBLIC KEY BLOCK----- +""" + +PRIVATE_KEY_2 = """ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +lQHYBFGMCV4BBADG0yh7jyefxpN+JfWdOn/tFgl0w13bXtVAaA7WdXqwG7nYAuDD +kYKriqqI9x4cNPyC6ifPBnDiZiiv2xKCALimqpcwxe1AGKTrD2WWJrUXzwtqUwp1 +6mdb3Xqi8E21LKal35ZApBbX4RijKuax/BleWt7V2ZEVmYXTcIVV2WoAtwARAQAB +AAP7BLuSAx7tOohnimEs74ks8l/L6dOcsFQZj2bqs4AoY3jFe7bV0tHr4llypb/8 +H3/DYvpf6DWnCjyUS1tTnXSW8JXtx01BUKaAufSmMNg9blKV6GGHlT/Whe9uVyks +7XHk/+9mebVMNJ/kNlqq2k+uWqJohzC8WWLRK+d1tBeqDsECANZmzltPaqUsGV5X +C3zszE3tUBgptV/mKnBtopKi+VH+t7K6fudGcG+bAcZDUoH/QVde52mIIjjIdLje +uajJuHUCAO1mqh+vPoGv4eBLV7iBo3XrunyGXiys4a39eomhxTy3YktQanjjx+ty +GltAGCs5PbWGO6/IRjjvd46wh53kzvsCAO0J97gsWhzLuFnkxFAJSPk7RRlyl7lI +1XS/x0Og6j9XHCyY1OYkfBm0to3UlCfkgirzCYlTYObCofzdKFIPDmSqHbQhYW5v +dGhlcnVzZXIgPGFub3RoZXJ1c2VyQGxlYXAuc2U+iLgEEwECACIFAlGMCV4CGwMG +CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEH+d+mh/7ldai24D/i0s3gSBSvsh +8vLYeQcDHPDsDiup8w33YMgz2ZmsMZpZGs6fdpUXtVTVQbswOQd8++n9wXB7OgLD +izgigdVz+lWU6RwdLK3j9F+Hbjy1gQmYUIlcYemQrzdUgpgkCK2E1xwnpDgkT+jT +oy1/i6H9wDUdQvhrhx6pSG2kslQst4qjnQHYBFGMCV4BBADsyQI7GR0wSAxzVayL +juPzgT+bjbFeymIhjuxKIEwnIKwYkovztW+4bbOcQs785k3Lp6RzvigTpQQtZ/hw +cLOqZbZw8t/24+D+Pq9mMP2uUvCFFqLlVvA6D3vKSQ/XNN+YB919WQ04jh63yuRe +94WenT1RJd6xU1aaUff4rKizuQARAQABAAP9EyElqJ3dq3EErXwwT4mMnbd1SrVC +rUJrNWQZL59mm5oigS00uIyR0SvusOr+UzTtd8ysRuwHy5d/LAZsbjQStaOMBILx +77TJveOel0a1QK0YSMF2ywZMCKvquvjli4hAtWYz/EwfuzQN3t23jc5ny+GqmqD2 +3FUxLJosFUfLNmECAO9KhVmJi+L9dswIs+2Dkjd1eiRQzNOEVffvYkGYZyKxNiXF +UA5kvyZcB4iAN9sWCybE4WHZ9jd4myGB0MPDGxkCAP1RsXJbbuD6zS7BXe5gwunO +2q4q7ptdSl/sJYQuTe1KNP5d/uGsvlcFfsYjpsopasPjFBIncc/2QThMKlhoEaEB +/0mVAxpT6SrEvUbJ18z7kna24SgMPr3OnPMxPGfvNLJY/Xv/A17YfoqjmByCvsKE +JCDjopXtmbcrZyoEZbEht9mko4ifBBgBAgAJBQJRjAleAhsMAAoJEH+d+mh/7lda +z2UEAKgs0crDpbvHs+z7ogQ+Enm4EalpcWtUxdbo83y5rj4r0TmdlysOWkLLcYBk +o6Ae7WnOPbNIboeF/FyvgbSQX1POCUvCXNrGrZX8KMmd+Sx+rA2XJCPkUv98Hus6 +THx7N776fcYHGumbqUMYrxrcZSbNveE6SaK8fphRam1dewM0 +=a5gs +-----END PGP PRIVATE KEY BLOCK----- +""" | 
