aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/primitives/block/ciphers.py22
-rw-r--r--docs/primitives/symmetric-encryption.rst17
-rw-r--r--tests/primitives/test_nist.py73
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),
+ )