diff options
-rw-r--r-- | changes/feature_openpgp-sign-verify | 1 | ||||
-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 |
4 files changed, 428 insertions, 126 deletions
diff --git a/changes/feature_openpgp-sign-verify b/changes/feature_openpgp-sign-verify new file mode 100644 index 0000000..9422edc --- /dev/null +++ b/changes/feature_openpgp-sign-verify @@ -0,0 +1 @@ + o Add OpenPGP sign/verify 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----- +""" |