test all error-cases, and some fixups

This commit is contained in:
meejah 2019-06-17 21:56:06 -06:00
parent 802f1afde6
commit a27a5ce581
5 changed files with 209 additions and 5 deletions

View File

@ -112,6 +112,7 @@ def verify_signature(public_key, alleged_signature, data):
:param bytes data: the data which was allegedly signed :param bytes data: the data which was allegedly signed
""" """
_validate_public_key(public_key)
try: try:
public_key.verify( public_key.verify(
alleged_signature, alleged_signature,
@ -133,7 +134,7 @@ def _validate_public_key(public_key):
""" """
if not isinstance(public_key, rsa.RSAPublicKey): if not isinstance(public_key, rsa.RSAPublicKey):
raise ValueError( raise ValueError(
"public_key not an RSAPublicKey" "public_key must be an RSAPublicKey"
) )
@ -144,5 +145,5 @@ def _validate_private_key(private_key):
""" """
if not isinstance(private_key, rsa.RSAPrivateKey): if not isinstance(private_key, rsa.RSAPrivateKey):
raise ValueError( raise ValueError(
"private_key not an RSAPrivateKey" "private_key must be an RSAPrivateKey"
) )

View File

@ -5,8 +5,14 @@ from base64 import b64decode
from binascii import a2b_hex, b2a_hex from binascii import a2b_hex, b2a_hex
from os import path from os import path
from allmydata.crypto import aes from allmydata.crypto import (
from allmydata.crypto import ed25519, rsa aes,
ed25519,
rsa,
remove_prefix,
BadPrefixError
)
RESOURCE_DIR = path.join(path.dirname(__file__), 'data') RESOURCE_DIR = path.join(path.dirname(__file__), 'data')
@ -219,6 +225,55 @@ class TestRegression(unittest.TestCase):
priv_key, pub_key = rsa.create_signing_keypair_from_string(self.RSA_2048_PRIV_KEY) priv_key, pub_key = rsa.create_signing_keypair_from_string(self.RSA_2048_PRIV_KEY)
rsa.verify_signature(pub_key, self.RSA_2048_SIG, b'test') rsa.verify_signature(pub_key, self.RSA_2048_SIG, b'test')
def test_encrypt_data_not_bytes(self):
'''
only bytes can be encrypted
'''
key = '\x00' * 16
encryptor = aes.create_encryptor(key)
with self.assertRaises(ValueError) as ctx:
aes.encrypt_data(encryptor, six.text_type("not bytes"))
self.assertIn(
"was not bytes",
str(ctx.exception)
)
def test_key_incorrect_size(self):
'''
only bytes can be encrypted
'''
key = '\x00' * 12
with self.assertRaises(ValueError) as ctx:
encryptor = aes.create_encryptor(key)
self.assertIn(
"16 or 32 bytes long",
str(ctx.exception)
)
def test_iv_not_bytes(self):
'''
iv must be bytes
'''
key = '\x00' * 16
with self.assertRaises(TypeError) as ctx:
encryptor = aes.create_encryptor(key, iv=six.text_type("1234567890abcdef"))
self.assertIn(
"was not bytes",
str(ctx.exception)
)
def test_incorrect_iv_size(self):
'''
iv must be 16 bytes
'''
key = '\x00' * 16
with self.assertRaises(ValueError) as ctx:
encryptor = aes.create_encryptor(key, iv='\x00' * 3)
self.assertIn(
"16 bytes long",
str(ctx.exception)
)
class TestEd25519(unittest.TestCase): class TestEd25519(unittest.TestCase):
@ -252,6 +307,88 @@ class TestEd25519(unittest.TestCase):
ed25519.bytes_from_verifying_key(public_key2), ed25519.bytes_from_verifying_key(public_key2),
) )
def test_deserialize_private_not_bytes(self):
'''
serialized key must be bytes
'''
with self.assertRaises(ValueError) as ctx:
ed25519.signing_keypair_from_bytes(six.text_type("not bytes"))
self.assertIn(
"must be bytes",
str(ctx.exception)
)
def test_deserialize_public_not_bytes(self):
'''
serialized key must be bytes
'''
with self.assertRaises(ValueError) as ctx:
ed25519.verifying_key_from_bytes(six.text_type("not bytes"))
self.assertIn(
"must be bytes",
str(ctx.exception)
)
def test_signed_data_not_bytes(self):
'''
data to sign must be bytes
'''
priv, pub = ed25519.create_signing_keypair()
with self.assertRaises(ValueError) as ctx:
ed25519.sign_data(priv, six.text_type("not bytes"))
self.assertIn(
"must be bytes",
str(ctx.exception)
)
def test_signature_not_bytes(self):
'''
signature must be bytes
'''
priv, pub = ed25519.create_signing_keypair()
with self.assertRaises(ValueError) as ctx:
ed25519.verify_signature(pub, six.text_type("not bytes"), b"data")
self.assertIn(
"must be bytes",
str(ctx.exception)
)
def test_signature_data_not_bytes(self):
'''
signature must be bytes
'''
priv, pub = ed25519.create_signing_keypair()
with self.assertRaises(ValueError) as ctx:
ed25519.verify_signature(pub, b"signature", six.text_type("not bytes"))
self.assertIn(
"must be bytes",
str(ctx.exception)
)
def test_sign_invalid_pubkey(self):
'''
pubkey must be correct
'''
priv, pub = ed25519.create_signing_keypair()
with self.assertRaises(ValueError) as ctx:
ed25519.sign_data(object(), b"data")
self.assertIn(
"must be an Ed25519PrivateKey",
str(ctx.exception)
)
def test_verify_invalid_pubkey(self):
'''
pubkey must be correct
'''
priv, pub = ed25519.create_signing_keypair()
with self.assertRaises(ValueError) as ctx:
ed25519.verify_signature(object(), b"signature", b"data")
self.assertIn(
"must be an Ed25519PublicKey",
str(ctx.exception)
)
class TestRsa(unittest.TestCase): class TestRsa(unittest.TestCase):
@ -279,3 +416,40 @@ class TestRsa(unittest.TestCase):
# ..and a failed way # ..and a failed way
with self.assertRaises(rsa.BadSignature): with self.assertRaises(rsa.BadSignature):
rsa.verify_signature(pub_key, sig1, data_to_sign + b"more") rsa.verify_signature(pub_key, sig1, data_to_sign + b"more")
def test_sign_invalid_pubkey(self):
'''
pubkey must be correct
'''
priv, pub = rsa.create_signing_keypair(1024)
with self.assertRaises(ValueError) as ctx:
rsa.sign_data(object(), b"data")
self.assertIn(
"must be an RSAPrivateKey",
str(ctx.exception)
)
def test_verify_invalid_pubkey(self):
'''
pubkey must be correct
'''
priv, pub = rsa.create_signing_keypair(1024)
with self.assertRaises(ValueError) as ctx:
rsa.verify_signature(object(), b"signature", b"data")
self.assertIn(
"must be an RSAPublicKey",
str(ctx.exception)
)
class TestUtil(unittest.TestCase):
def test_remove_prefix_good(self):
self.assertEquals(
remove_prefix(b"foobar", b"foo"),
b"bar"
)
def test_remove_prefix_bad(self):
with self.assertRaises(BadPrefixError):
remove_prefix(b"foobar", b"bar")

View File

@ -1012,6 +1012,27 @@ class Signatures(SyncTestCase):
self.failUnlessRaises(UnknownKeyError, self.failUnlessRaises(UnknownKeyError,
unsign_from_foolscap, (bad_msg, sig, "v999-key")) unsign_from_foolscap, (bad_msg, sig, "v999-key"))
def test_unsigned_announcement(self):
from allmydata.crypto import ed25519
ed25519.verifying_key_from_string("pub-v0-wodst6ly4f7i7akt2nxizsmmy2rlmer6apltl56zctn67wfyu5tq")
mock_tub = Mock()
ic = IntroducerClient(
mock_tub,
u"pb://",
u"fake_nick",
"0.0.0",
"1.2.3",
{},
(0, u"i am a nonce"),
"invalid",
)
self.assertEqual(0, ic._debug_counts["inbound_announcement"])
ic.got_announcements([
("message", "v0-aaaaaaa", "v0-wodst6ly4f7i7akt2nxizsmmy2rlmer6apltl56zctn67wfyu5tq")
])
# we should have rejected this announcement due to a bad signature
self.assertEqual(0, ic._debug_counts["inbound_announcement"])
# add tests of StorageFarmBroker: if it receives duplicate announcements, it # add tests of StorageFarmBroker: if it receives duplicate announcements, it
# should leave the Reconnector in place, also if it receives # should leave the Reconnector in place, also if it receives

View File

@ -788,6 +788,14 @@ class FileUtil(ReallyEqualMixin, unittest.TestCase):
self.failUnlessFalse(symlinkinfo.isfile) self.failUnlessFalse(symlinkinfo.isfile)
self.failUnlessFalse(symlinkinfo.isdir) self.failUnlessFalse(symlinkinfo.isdir)
def test_encrypted_tempfile(self):
from allmydata.util.fileutil import EncryptedTemporaryFile
f = EncryptedTemporaryFile()
f.write("foobar")
f.close()
print(f.file)
print(dir(f.file))
class PollMixinTests(unittest.TestCase): class PollMixinTests(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -112,7 +112,7 @@ class EncryptedTemporaryFile(object):
cipher = aes.create_encryptor(self.key, iv) cipher = aes.create_encryptor(self.key, iv)
# this is just to advance the counter # this is just to advance the counter
aes.encrypt_data(cipher, "\x00" * offset_small) aes.encrypt_data(cipher, "\x00" * offset_small)
return aes.encrypt_data(ciper, data) return aes.encrypt_data(cipher, data)
def close(self): def close(self):
self.file.close() self.file.close()