- implemented key protection such that unprotected private keys can be protected with passphrases, and already-protected passphrases can be re-protected with a new passphrase, and unit tests for these two scenarios - closes #149

- updated CI configs so that Python 3.2 can actually finish running the test suite without crashing since it is stuck on an older version of Cryptography
- added additional tests to test setup.py on all versions of Python after I noticed that a recent change would have made it break on Python 3.2
- enum34 should no longer be installed needlessly on Python 3.4 or newer
- added --no-cache-dir to tox's call to pip to install dependencies needed for testing
This commit is contained in:
Michael Greene
2015-06-11 19:55:07 -07:00
parent c76ba55ee5
commit 9c6d9636b4
9 changed files with 187 additions and 28 deletions

View File

@@ -2,6 +2,7 @@
"""
import pytest
import copy
import glob
import os
import time
@@ -195,6 +196,14 @@ def sessionkey():
return b'\x9d[\xc1\x0e\xec\x01k\xbc\xf4\x04UW\xbb\xfb\xb2\xb9'
def _compare_keys(keyA, keyB):
for Ai, Bi in zip(keyA._key.keymaterial, keyB._key.keymaterial):
if Ai != Bi:
return False
return True
key_algs = [ PubKeyAlgorithm.RSAEncryptOrSign, PubKeyAlgorithm.DSA, PubKeyAlgorithm.ECDSA ]
@@ -235,8 +244,31 @@ class TestPGPKey(object):
e.args += (warning.message,)
raise
def test_protect(self):
pytest.skip("not implemented yet")
def test_protect(self, sec):
if sec.key_algorithm == PubKeyAlgorithm.ECDSA:
pytest.skip("Cannot properly encrypt ECDSA keys yet")
assert sec.is_protected is False
# copy sec so we have a comparison point
sec2 = copy.deepcopy(sec)
# ensure that the key material values are the same
assert _compare_keys(sec, sec2)
sec2.protect('There Are Many Like It, But This Key Is Mine',
SymmetricKeyAlgorithm.AES256, HashAlgorithm.SHA256)
assert sec2.is_protected
assert sec2.is_unlocked is False
# ensure that sec2 is now
assert _compare_keys(sec, sec2) is False
assert sec2._key.keymaterial.__bytes__()[sec2._key.keymaterial.publen():] not in sec._key.keymaterial.__bytes__()
# unlock with the correct passphrase and compare the keys
with sec2.unlock('There Are Many Like It, But This Key Is Mine') as _unlocked:
assert _unlocked.is_unlocked
assert _compare_keys(sec, sec2)
def test_unlock(self, enc, sec):
assert enc.is_protected
@@ -248,6 +280,27 @@ class TestPGPKey(object):
assert _unlocked is enc
assert enc.is_unlocked
def test_change_passphrase(self, enc):
enc2 = copy.deepcopy(enc)
assert enc.is_protected
assert enc2.is_protected
assert enc.is_unlocked is False
assert enc2.is_unlocked is False
assert enc._key.keymaterial.encbytes == enc2._key.keymaterial.encbytes
# change the passphrase on enc2
with enc.unlock('QwertyUiop') as e1u, enc2.unlock('QwertyUiop') as e2u, self.assert_warnings():
assert _compare_keys(e1u, e2u)
enc2.protect('AsdfGhjkl', enc2._key.keymaterial.s2k.encalg, enc2._key.keymaterial.s2k.halg)
assert enc._key.keymaterial.encbytes != enc2._key.keymaterial.encbytes
# unlock again and verify that we still have the same key hiding in there
with enc.unlock('QwertyUiop') as e1u, enc2.unlock('AsdfGhjkl') as e2u, self.assert_warnings():
assert _compare_keys(e1u, e2u)
def test_verify_detached(self, sigkey, sigsig, sigsubj):
assert sigkey.verify(_read(sigsubj), sigsig)