|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Self-test suite for Crypto.Cipher.DES3""" |
|
|
|
|
|
import unittest |
|
|
from binascii import hexlify, unhexlify |
|
|
|
|
|
from Crypto.Cipher import DES3 |
|
|
|
|
|
from Crypto.Util.strxor import strxor_c |
|
|
from Crypto.Util.py3compat import bchr, tostr |
|
|
from Crypto.SelfTest.loader import load_test_vectors |
|
|
from Crypto.SelfTest.st_common import list_test_cases |
|
|
|
|
|
|
|
|
test_data = [ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
('54686520717566636b2062726f776e20666f78206a756d70', |
|
|
'a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900', |
|
|
'0123456789abcdef23456789abcdef01456789abcdef0123', |
|
|
'NIST SP800-67 B.1'), |
|
|
|
|
|
|
|
|
|
|
|
('21e81b7ade88a259', '5c577d4d9b20c0f8', |
|
|
'9b397ebf81b1181e282f4bb8adbadc6b', 'Two-key 3DES'), |
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
nist_tdes_mmt_files = ("TECBMMT2.rsp", "TECBMMT3.rsp") |
|
|
|
|
|
for tdes_file in nist_tdes_mmt_files: |
|
|
|
|
|
test_vectors = load_test_vectors( |
|
|
("Cipher", "TDES"), |
|
|
tdes_file, |
|
|
"TDES ECB (%s)" % tdes_file, |
|
|
{"count": lambda x: int(x)}) or [] |
|
|
|
|
|
for index, tv in enumerate(test_vectors): |
|
|
|
|
|
|
|
|
if isinstance(tv, str): |
|
|
continue |
|
|
|
|
|
key = tv.key1 + tv.key2 + tv.key3 |
|
|
test_data_item = (tostr(hexlify(tv.plaintext)), |
|
|
tostr(hexlify(tv.ciphertext)), |
|
|
tostr(hexlify(key)), |
|
|
"%s (%s)" % (tdes_file, index)) |
|
|
test_data.append(test_data_item) |
|
|
|
|
|
|
|
|
class CheckParity(unittest.TestCase): |
|
|
|
|
|
def test_parity_option2(self): |
|
|
before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF") |
|
|
after_2k = DES3.adjust_key_parity(before_2k) |
|
|
self.assertEqual(after_2k, |
|
|
unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF")) |
|
|
|
|
|
def test_parity_option3(self): |
|
|
before_3k = unhexlify("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC") |
|
|
after_3k = DES3.adjust_key_parity(before_3k) |
|
|
self.assertEqual(after_3k, |
|
|
unhexlify("ABABABABABABABABBABABABABABABABACDCDCDCDCDCDCDCD")) |
|
|
|
|
|
def test_degradation(self): |
|
|
sub_key1 = bchr(1) * 8 |
|
|
sub_key2 = bchr(255) * 8 |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.adjust_key_parity, |
|
|
sub_key1 * 2 + sub_key2) |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.adjust_key_parity, |
|
|
sub_key1 + sub_key2 * 2) |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.adjust_key_parity, |
|
|
sub_key1 * 3) |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.adjust_key_parity, |
|
|
sub_key1 + strxor_c(sub_key1, 1) + sub_key2) |
|
|
|
|
|
|
|
|
class DegenerateToDESTest(unittest.TestCase): |
|
|
|
|
|
def runTest(self): |
|
|
sub_key1 = bchr(1) * 8 |
|
|
sub_key2 = bchr(255) * 8 |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.new, |
|
|
sub_key1 * 2 + sub_key2, |
|
|
DES3.MODE_ECB) |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.new, |
|
|
sub_key1 + sub_key2 * 2, |
|
|
DES3.MODE_ECB) |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.new, |
|
|
sub_key1 * 3, |
|
|
DES3.MODE_ECB) |
|
|
|
|
|
|
|
|
self.assertRaises(ValueError, DES3.new, |
|
|
sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1), |
|
|
DES3.MODE_ECB) |
|
|
|
|
|
|
|
|
class TestOutput(unittest.TestCase): |
|
|
|
|
|
def runTest(self): |
|
|
|
|
|
|
|
|
cipher = DES3.new(b'4'*8 + b'G'*8 + b'T'*8, DES3.MODE_ECB) |
|
|
|
|
|
pt = b'5' * 16 |
|
|
ct = cipher.encrypt(pt) |
|
|
|
|
|
output = bytearray(16) |
|
|
res = cipher.encrypt(pt, output=output) |
|
|
self.assertEqual(ct, output) |
|
|
self.assertEqual(res, None) |
|
|
|
|
|
res = cipher.decrypt(ct, output=output) |
|
|
self.assertEqual(pt, output) |
|
|
self.assertEqual(res, None) |
|
|
|
|
|
output = memoryview(bytearray(16)) |
|
|
cipher.encrypt(pt, output=output) |
|
|
self.assertEqual(ct, output) |
|
|
|
|
|
cipher.decrypt(ct, output=output) |
|
|
self.assertEqual(pt, output) |
|
|
|
|
|
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16) |
|
|
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) |
|
|
|
|
|
shorter_output = bytearray(7) |
|
|
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) |
|
|
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) |
|
|
|
|
|
|
|
|
def get_tests(config={}): |
|
|
from .common import make_block_tests |
|
|
|
|
|
tests = [] |
|
|
tests = make_block_tests(DES3, "DES3", test_data) |
|
|
tests.append(DegenerateToDESTest()) |
|
|
tests += list_test_cases(CheckParity) |
|
|
tests += [TestOutput()] |
|
|
return tests |
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
import unittest |
|
|
|
|
|
def suite(): |
|
|
unittest.TestSuite(get_tests()) |
|
|
|
|
|
unittest.main(defaultTest='suite') |
|
|
|
|
|
|
|
|
|