diff options
-rw-r--r-- | cryptography/primitives/block/ciphers.py | 22 | ||||
-rw-r--r-- | docs/primitives/symmetric-encryption.rst | 17 | ||||
-rw-r--r-- | tests/primitives/test_nist.py | 73 |
3 files changed, 112 insertions, 0 deletions
diff --git a/cryptography/primitives/block/ciphers.py b/cryptography/primitives/block/ciphers.py index 4ac150a4..f10a349a 100644 --- a/cryptography/primitives/block/ciphers.py +++ b/cryptography/primitives/block/ciphers.py @@ -52,3 +52,25 @@ class Camellia(object): @property def key_size(self): return len(self.key) * 8 + + +class TripleDES(object): + name = "3DES" + block_size = 64 + # TODO: is there a better way to represent the fact that the effective key + # size is 56 bits? + key_sizes = set([64, 128, 192]) + + def __init__(self, key): + super(TripleDES, self).__init__() + self.key = key + + # Verify that the key size matches the expected key size + if self.key_size not in self.key_sizes: + raise ValueError("Invalid key size ({0}) for {1}".format( + self.key_size, self.name + )) + + @property + def key_size(self): + return len(self.key) * 8 diff --git a/docs/primitives/symmetric-encryption.rst b/docs/primitives/symmetric-encryption.rst index 7899e67d..cf251c91 100644 --- a/docs/primitives/symmetric-encryption.rst +++ b/docs/primitives/symmetric-encryption.rst @@ -61,6 +61,23 @@ Ciphers This must be kept secret. +.. class:: cryptography.primitives.block.ciphers.TripleDES(key) + + Triple DES (Data Encryption Standard), sometimes refered to as 3DES, is a + block cipher standardized by NIST. Triple DES has known cryptoanalytic + flaws, however none of them currently enable a practical attack. + Nonetheless, Triples DES is not reccomended for new applications because it + is incredibly slow, old applications should consider moving away from it. + + :param bytes key: The secret key, either ``64``, ``128``, or ``192`` bits + (note that DES functionally uses ``56``, ``112``, or + ``168`` bits of the key, there is a parity byte in each + component of the key), in some materials these are + referred to as being up to three separate keys (each + ``56`` bits long), they can simply be concatenated to + produce the full key. This must be kept secret. + + Modes ~~~~~ diff --git a/tests/primitives/test_nist.py b/tests/primitives/test_nist.py index d97b207b..8c8a3818 100644 --- a/tests/primitives/test_nist.py +++ b/tests/primitives/test_nist.py @@ -26,6 +26,16 @@ from .utils import generate_encrypt_test from ..utils import load_nist_vectors_from_file +def load_3des_nist_vectors_from_file(path, op): + vectors = load_nist_vectors_from_file(path, op) + for vector in vectors: + vector["ciphertext"] = vector["ciphertext3"] + del vector["ciphertext1"] + del vector["ciphertext2"] + del vector["ciphertext3"] + return vectors + + class TestAES_CBC(object): test_KAT = generate_encrypt_test( lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), @@ -164,3 +174,66 @@ class TestAES_CFB(object): lambda key, iv: ciphers.AES(binascii.unhexlify(key)), lambda key, iv: modes.CFB(binascii.unhexlify(iv)), ) + + +class TestTripleDES_CBC(object): + test_KAT1 = generate_encrypt_test( + lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + os.path.join("3DES", "KAT"), + [ + "TCBCinvperm.rsp", + "TCBCpermop.rsp", + "TCBCsubtab.rsp", + "TCBCvarkey.rsp", + "TCBCvartext.rsp", + ], + lambda keys, iv: ciphers.TripleDES(binascii.unhexlify(keys)), + lambda keys, iv: modes.CBC(iv), + ) + + test_KAT2 = generate_encrypt_test( + lambda path: load_3des_nist_vectors_from_file(path, "ENCRYPT"), + os.path.join("3DES", "KAT"), + [ + "TCBCIpermop.rsp", + "TCBCIsubtab.rsp", + "TCBCIvarkey.rsp", + "TCBCIvartext.rsp", + ], + lambda keys, iv1, iv2, iv3: ciphers.TripleDES(binascii.unhexlify(keys)), + lambda keys, iv1, iv2, iv3: modes.CBC(iv1 + iv2 + iv3), + ) + + test_KAT3 = generate_encrypt_test( + lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + os.path.join("3DES", "KAT"), + [ + "TCBCIinvperm.rsp", + ], + lambda keys, iv1, iv2, iv3: ciphers.TripleDES(binascii.unhexlify(keys)), + lambda keys, iv1, iv2, iv3: modes.CBC(iv1 + iv2 + iv3), + ) + + test_MMT1 = generate_encrypt_test( + lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + os.path.join("3DES", "MMT"), + [ + "TCBCIMMT1.rsp", + "TCBCIMMT2.rsp", + "TCBCIMMT3.rsp", + ], + lambda key1, key2, key3, iv1, iv2, iv3: ciphers.TripleDES(binascii.unhexlify(key1 + key2 + key3)), + lambda key1, key2, key3, iv1, iv2, iv3: modes.CBC(iv1 + iv2 + iv3), + ) + + test_MMT1 = generate_encrypt_test( + lambda path: load_nist_vectors_from_file(path, "ENCRYPT"), + os.path.join("3DES", "MMT"), + [ + "TCBCMMT1.rsp", + "TCBCMMT2.rsp", + "TCBCMMT3.rsp", + ], + lambda key1, key2, key3, iv: ciphers.TripleDES(binascii.unhexlify(key1 + key2 + key3)), + lambda key1, key2, key3, iv: modes.CBC(iv), + ) |