1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

cryptsuite: add an assertEqualBin() helper function.

This is just like assertEqual, except that I use it when I'm comparing
random-looking binary data, and if the check fails it will encode the
two differing values in hex, which is easier to read than trying to
express them as really strange-looking string literals.
This commit is contained in:
Simon Tatham 2019-01-09 21:59:19 +00:00
parent 3347bd81b7
commit b7be22e4e0

View File

@ -127,7 +127,14 @@ def mac_str(alg, key, message, cipher=None):
ssh2_mac_update(m, message)
return ssh2_mac_genresult(m)
class mpint(unittest.TestCase):
class MyTestBase(unittest.TestCase):
"Intermediate class that adds useful helper methods."
def assertEqualBin(self, x, y):
# Like assertEqual, but produces more legible error reports
# for random-looking binary data.
self.assertEqual(x.encode('hex'), y.encode('hex'))
class mpint(MyTestBase):
def testCreation(self):
self.assertEqual(int(mp_new(128)), 0)
self.assertEqual(int(mp_from_bytes_be(b'ABCDEFGHIJKLMNOP')),
@ -544,7 +551,7 @@ class mpint(unittest.TestCase):
v = int(mp_random_in_range(lo, hi))
self.assertTrue(lo <= v < hi)
class ecc(unittest.TestCase):
class ecc(MyTestBase):
def testWeierstrassSimple(self):
# Simple tests using a Weierstrass curve I made up myself,
# which (unlike the ones used for serious crypto) is small
@ -746,7 +753,7 @@ class ecc(unittest.TestCase):
self.assertEqual(int(x), int(rGi.x))
self.assertEqual(int(y), int(rGi.y))
class crypt(unittest.TestCase):
class crypt(MyTestBase):
def testSSH1Fingerprint(self):
# Example key and reference fingerprint value generated by
# OpenSSH 6.7 ssh-keygen
@ -764,9 +771,9 @@ class crypt(unittest.TestCase):
c = ssh2_cipher_new(cipher)
ssh2_cipher_setkey(c, key)
ssh2_cipher_setiv(c, iv)
self.assertEqual(ssh2_cipher_encrypt(c, plaintext), ciphertext)
self.assertEqualBin(ssh2_cipher_encrypt(c, plaintext), ciphertext)
ssh2_cipher_setiv(c, iv)
self.assertEqual(ssh2_cipher_decrypt(c, ciphertext), plaintext)
self.assertEqualBin(ssh2_cipher_decrypt(c, ciphertext), plaintext)
# Tests of CBC mode.
@ -855,7 +862,7 @@ class crypt(unittest.TestCase):
dc0 = ssh2_cipher_decrypt(cbc, ec0)
ssh2_cipher_setiv(cbc, b'\x00' * 16)
dc1 = ssh2_cipher_decrypt(cbc, ec1)
self.assertEqual(iv, dc0)
self.assertEqualBin(iv, dc0)
return dc1
def test(keylen, ivInteger):
@ -865,7 +872,7 @@ class crypt(unittest.TestCase):
ivIntegerInc = (ivInteger + 1) & mask
ivBinaryInc = unhex("{:032x}".format((ivIntegerInc)))
actualResult = increment(keylen, ivBinary)
self.assertEqual(actualResult, ivBinaryInc)
self.assertEqualBin(actualResult, ivBinaryInc)
# Check every input IV you can make by gluing together 32-bit
# pieces of the form 0, 1 or -1. This should test all the
@ -881,7 +888,7 @@ class crypt(unittest.TestCase):
ivInteger = int("".join(ivHexBytes), 16)
test(keylen, ivInteger)
class standard_test_vectors(unittest.TestCase):
class standard_test_vectors(MyTestBase):
def testAES(self):
def vector(cipher, key, plaintext, ciphertext):
c = ssh2_cipher_new(cipher)
@ -894,10 +901,10 @@ class standard_test_vectors(unittest.TestCase):
# each operation.
ssh2_cipher_setiv(c, b'\x00' * 16)
self.assertEqual(ssh2_cipher_encrypt(c, plaintext), ciphertext)
self.assertEqualBin(ssh2_cipher_encrypt(c, plaintext), ciphertext)
ssh2_cipher_setiv(c, b'\x00' * 16)
self.assertEqual(ssh2_cipher_decrypt(c, ciphertext), plaintext)
self.assertEqualBin(ssh2_cipher_decrypt(c, ciphertext), plaintext)
# The test vectors from FIPS 197 appendix C: the key bytes go
# 00 01 02 03 ... for as long as needed, and the plaintext
@ -915,50 +922,53 @@ class standard_test_vectors(unittest.TestCase):
MD5 = lambda s: hash_str('md5', s)
# The test vectors from RFC 1321 section A.5.
self.assertEqual(MD5(""), unhex('d41d8cd98f00b204e9800998ecf8427e'))
self.assertEqual(MD5("a"), unhex('0cc175b9c0f1b6a831c399e269772661'))
self.assertEqual(MD5("abc"), unhex('900150983cd24fb0d6963f7d28e17f72'))
self.assertEqual(MD5("message digest"),
unhex('f96b697d7cb7938d525a2f31aaf161d0'))
self.assertEqual(MD5("abcdefghijklmnopqrstuvwxyz"),
unhex('c3fcd3d76192e4007dfb496cca67e13b'))
self.assertEqual(MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789"),
unhex('d174ab98d277d9f5a5611c2c9f419d9f'))
self.assertEqual(MD5("1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890"),
unhex('57edf4a22be3c955ac49da2e2107b67a'))
self.assertEqualBin(MD5(""),
unhex('d41d8cd98f00b204e9800998ecf8427e'))
self.assertEqualBin(MD5("a"),
unhex('0cc175b9c0f1b6a831c399e269772661'))
self.assertEqualBin(MD5("abc"),
unhex('900150983cd24fb0d6963f7d28e17f72'))
self.assertEqualBin(MD5("message digest"),
unhex('f96b697d7cb7938d525a2f31aaf161d0'))
self.assertEqualBin(MD5("abcdefghijklmnopqrstuvwxyz"),
unhex('c3fcd3d76192e4007dfb496cca67e13b'))
self.assertEqualBin(MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789"),
unhex('d174ab98d277d9f5a5611c2c9f419d9f'))
self.assertEqualBin(MD5("1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890"),
unhex('57edf4a22be3c955ac49da2e2107b67a'))
def testHmacMD5(self):
# The test vectors from the RFC 2104 Appendix.
self.assertEqual(mac_str('hmac_md5', unhex('0b'*16), "Hi There"),
self.assertEqualBin(mac_str('hmac_md5', unhex('0b'*16), "Hi There"),
unhex('9294727a3638bb1c13f48ef8158bfc9d'))
self.assertEqual(mac_str('hmac_md5', "Jefe",
self.assertEqualBin(mac_str('hmac_md5', "Jefe",
"what do ya want for nothing?"),
unhex('750c783e6ab0b503eaa86e310a5db738'))
self.assertEqual(mac_str('hmac_md5', unhex('aa'*16), unhex('dd'*50)),
self.assertEqualBin(mac_str('hmac_md5', unhex('aa'*16), unhex('dd'*50)),
unhex('56be34521d144c88dbb8c733f0e8b3f6'))
def testSHA1(self):
# Test cases from RFC 6234 section 8.5, omitting the ones
# whose input is not a multiple of 8 bits
self.assertEqual(hash_str('sha1', "abc"), unhex(
self.assertEqualBin(hash_str('sha1', "abc"), unhex(
"a9993e364706816aba3e25717850c26c9cd0d89d"))
self.assertEqual(hash_str('sha1',
self.assertEqualBin(hash_str('sha1',
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), unhex(
"84983e441c3bd26ebaae4aa1f95129e5e54670f1"))
self.assertEqual(hash_str_iter('sha1',
self.assertEqualBin(hash_str_iter('sha1',
("a" * 1000 for _ in range(1000))), unhex(
"34aa973cd4c4daa4f61eeb2bdbad27316534016f"))
self.assertEqual(hash_str('sha1',
self.assertEqualBin(hash_str('sha1',
"01234567012345670123456701234567" * 20), unhex(
"dea356a2cddd90c7a7ecedc5ebb563934f460452"))
self.assertEqual(hash_str('sha1', b"\x5e"), unhex(
self.assertEqualBin(hash_str('sha1', b"\x5e"), unhex(
"5e6f80a34a9798cafc6a5db96cc57ba4c4db59c2"))
self.assertEqual(hash_str('sha1',
self.assertEqualBin(hash_str('sha1',
unhex("9a7dfdf1ecead06ed646aa55fe757146")), unhex(
"82abff6605dbe1c17def12a394fa22a82b544a35"))
self.assertEqual(hash_str('sha1', unhex(
self.assertEqualBin(hash_str('sha1', unhex(
"f78f92141bcd170ae89b4fba15a1d59f3fd84d223c9251bdacbbae61d05ed115"
"a06a7ce117b7beead24421ded9c32592bd57edeae39c39fa1fe8946a84d0cf1f"
"7beead1713e2e0959897347f67c80b0400c209815d6b10a683836fd5562a56ca"
@ -970,23 +980,23 @@ class standard_test_vectors(unittest.TestCase):
def testSHA256(self):
# Test cases from RFC 6234 section 8.5, omitting the ones
# whose input is not a multiple of 8 bits
self.assertEqual(hash_str('sha256', "abc"), unhex(
self.assertEqualBin(hash_str('sha256', "abc"), unhex(
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"))
self.assertEqual(hash_str('sha256',
self.assertEqualBin(hash_str('sha256',
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), unhex(
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"))
self.assertEqual(hash_str_iter('sha256',
self.assertEqualBin(hash_str_iter('sha256',
("a" * 1000 for _ in range(1000))), unhex(
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"))
self.assertEqual(hash_str('sha256',
self.assertEqualBin(hash_str('sha256',
"01234567012345670123456701234567" * 20), unhex(
"594847328451bdfa85056225462cc1d867d877fb388df0ce35f25ab5562bfbb5"))
self.assertEqual(hash_str('sha256', b"\x19"), unhex(
self.assertEqualBin(hash_str('sha256', b"\x19"), unhex(
"68aa2e2ee5dff96e3355e6c7ee373e3d6a4e17f75f9518d843709c0c9bc3e3d4"))
self.assertEqual(hash_str('sha256',
self.assertEqualBin(hash_str('sha256',
unhex("e3d72570dcdd787ce3887ab2cd684652")), unhex(
"175ee69b02ba9b58e2b0a5fd13819cea573f3940a94f825128cf4209beabb4e8"))
self.assertEqual(hash_str('sha256', unhex(
self.assertEqualBin(hash_str('sha256', unhex(
"8326754e2277372f4fc12b20527afef04d8a056971b11ad57123a7c137760000"
"d7bef6f3c1f7a9083aa39d810db310777dab8b1e7f02b84a26c773325f8b2374"
"de7a4b5a58cb5c5cf35bcee6fb946e5bd694fa593a8beb3f9d6592ecedaa66ca"
@ -998,30 +1008,30 @@ class standard_test_vectors(unittest.TestCase):
def testSHA384(self):
# Test cases from RFC 6234 section 8.5, omitting the ones
# whose input is not a multiple of 8 bits
self.assertEqual(hash_str('sha384', "abc"), unhex(
self.assertEqualBin(hash_str('sha384', "abc"), unhex(
'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded163'
'1a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7'))
self.assertEqual(hash_str('sha384',
self.assertEqualBin(hash_str('sha384',
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), unhex(
'09330c33f71147e83d192fc782cd1b4753111b173b3b05d2'
'2fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039'))
self.assertEqual(hash_str_iter('sha384',
self.assertEqualBin(hash_str_iter('sha384',
("a" * 1000 for _ in range(1000))), unhex(
'9d0e1809716474cb086e834e310a4a1ced149e9c00f24852'
'7972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985'))
self.assertEqual(hash_str('sha384',
self.assertEqualBin(hash_str('sha384',
"01234567012345670123456701234567" * 20), unhex(
'2fc64a4f500ddb6828f6a3430b8dd72a368eb7f3a8322a70'
'bc84275b9c0b3ab00d27a5cc3c2d224aa6b61a0d79fb4596'))
self.assertEqual(hash_str('sha384', b"\xB9"), unhex(
self.assertEqualBin(hash_str('sha384', b"\xB9"), unhex(
'bc8089a19007c0b14195f4ecc74094fec64f01f90929282c'
'2fb392881578208ad466828b1c6c283d2722cf0ad1ab6938'))
self.assertEqual(hash_str('sha384',
self.assertEqualBin(hash_str('sha384',
unhex("a41c497779c0375ff10a7f4e08591739")), unhex(
'c9a68443a005812256b8ec76b00516f0dbb74fab26d66591'
'3f194b6ffb0e91ea9967566b58109cbc675cc208e4c823f7'))
self.assertEqual(hash_str('sha384', unhex(
self.assertEqualBin(hash_str('sha384', unhex(
"399669e28f6b9c6dbcbb6912ec10ffcf74790349b7dc8fbe4a8e7b3b5621db0f"
"3e7dc87f823264bbe40d1811c9ea2061e1c84ad10a23fac1727e7202fc3f5042"
"e6bf58cba8a2746e1f64f9b9ea352c711507053cf4e5339d52865f25cc22b5e8"
@ -1036,30 +1046,30 @@ class standard_test_vectors(unittest.TestCase):
def testSHA512(self):
# Test cases from RFC 6234 section 8.5, omitting the ones
# whose input is not a multiple of 8 bits
self.assertEqual(hash_str('sha512', "abc"), unhex(
self.assertEqualBin(hash_str('sha512', "abc"), unhex(
'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a'
'2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f'))
self.assertEqual(hash_str('sha512',
self.assertEqualBin(hash_str('sha512',
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), unhex(
'8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018'
'501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909'))
self.assertEqual(hash_str_iter('sha512',
self.assertEqualBin(hash_str_iter('sha512',
("a" * 1000 for _ in range(1000))), unhex(
'e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb'
'de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b'))
self.assertEqual(hash_str('sha512',
self.assertEqualBin(hash_str('sha512',
"01234567012345670123456701234567" * 20), unhex(
'89d05ba632c699c31231ded4ffc127d5a894dad412c0e024db872d1abd2ba814'
'1a0f85072a9be1e2aa04cf33c765cb510813a39cd5a84c4acaa64d3f3fb7bae9'))
self.assertEqual(hash_str('sha512', b"\xD0"), unhex(
self.assertEqualBin(hash_str('sha512', b"\xD0"), unhex(
'9992202938e882e73e20f6b69e68a0a7149090423d93c81bab3f21678d4aceee'
'e50e4e8cafada4c85a54ea8306826c4ad6e74cece9631bfa8a549b4ab3fbba15'))
self.assertEqual(hash_str('sha512',
self.assertEqualBin(hash_str('sha512',
unhex("8d4e3c0e3889191491816e9d98bff0a0")), unhex(
'cb0b67a4b8712cd73c9aabc0b199e9269b20844afb75acbdd1c153c9828924c3'
'ddedaafe669c5fdd0bc66f630f6773988213eb1b16f517ad0de4b2f0c95c90f8'))
self.assertEqual(hash_str('sha512', unhex(
self.assertEqualBin(hash_str('sha512', unhex(
"a55f20c411aad132807a502d65824e31a2305432aa3d06d3e282a8d84e0de1de"
"6974bf495469fc7f338f8054d58c26c49360c3e87af56523acf6d89d03e56ff2"
"f868002bc3e431edc44df2f0223d4bb3b243586e1a7d924936694fcbbaf88d95"
@ -1077,8 +1087,10 @@ class standard_test_vectors(unittest.TestCase):
# (Our implementation doesn't support that, because it knows
# it only has to deal with a fixed key length.)
def vector(key, message, s1, s256):
self.assertEqual(mac_str('hmac_sha1', key, message), unhex(s1))
self.assertEqual(mac_str('hmac_sha256', key, message), unhex(s256))
self.assertEqualBin(
mac_str('hmac_sha1', key, message), unhex(s1))
self.assertEqualBin(
mac_str('hmac_sha256', key, message), unhex(s256))
vector(
unhex("0b"*20), "Hi There",
"b617318655057264e28bc0b6fb378c8ef146be00",
@ -1116,7 +1128,7 @@ class standard_test_vectors(unittest.TestCase):
# by Ed25519. Getting that wrong would lead to no obvious
# failure, but would surely turn out to be a bad idea sooner
# or later...
self.assertEqual(ssh_key_sign(privkey, message, 0), sigblob)
self.assertEqualBin(ssh_key_sign(privkey, message, 0), sigblob)
# A cherry-picked example from DJB's test vector data at
# https://ed25519.cr.yp.to/python/sign.input, which is too