From 7e519450e447623c1cb900041998e78102b6b407 Mon Sep 17 00:00:00 2001 From: David Stainton Date: Wed, 12 Oct 2016 16:13:12 +0000 Subject: [PATCH] Add chacha20 python bindings fixes trac ticket https://tahoe-lafs.org/trac/pycryptopp/ticket/100 --- setup.py | 1 + src/pycryptopp/_pycryptoppmodule.cpp | 3 + src/pycryptopp/cipher/__init__.py | 3 +- src/pycryptopp/cipher/chacha20.py | 31 ++++ src/pycryptopp/cipher/chacha20module.cpp | 180 +++++++++++++++++++++++ src/pycryptopp/cipher/chacha20module.hpp | 6 + src/pycryptopp/test/test_chacha20.py | 132 +++++++++++++++++ src/pycryptopp/testvectors/chacha.txt | 120 +++++++++++++++ 8 files changed, 475 insertions(+), 1 deletion(-) create mode 100644 src/pycryptopp/cipher/chacha20.py create mode 100644 src/pycryptopp/cipher/chacha20module.cpp create mode 100644 src/pycryptopp/cipher/chacha20module.hpp create mode 100644 src/pycryptopp/test/test_chacha20.py create mode 100644 src/pycryptopp/testvectors/chacha.txt diff --git a/setup.py b/setup.py index e4fb8b4..a51426c 100644 --- a/setup.py +++ b/setup.py @@ -146,6 +146,7 @@ 'src/pycryptopp/hash/sha256module.cpp', 'src/pycryptopp/cipher/aesmodule.cpp', 'src/pycryptopp/cipher/xsalsa20module.cpp', + 'src/pycryptopp/cipher/chacha20module.cpp', ] if ECDSA: srcs.append('src/pycryptopp/publickey/ecdsamodule.cpp') diff --git a/src/pycryptopp/_pycryptoppmodule.cpp b/src/pycryptopp/_pycryptoppmodule.cpp index 1c99817..85370c8 100644 --- a/src/pycryptopp/_pycryptoppmodule.cpp +++ b/src/pycryptopp/_pycryptoppmodule.cpp @@ -5,6 +5,7 @@ #include "hash/sha256module.hpp" #include "cipher/aesmodule.hpp" #include "cipher/xsalsa20module.hpp" +#include "cipher/chacha20module.hpp" /* from Crypto++ */ #ifdef DISABLE_EMBEDDED_CRYPTOPP @@ -22,6 +23,7 @@ from pycryptopp.publickey import rsa\n\ from pycryptopp import cipher\n\ from pycryptopp.cipher import aes\n\ from pycryptopp.cipher import xsalsa20\n\ +from pycryptopp.cipher import chacha20\n\ from pycryptopp import hash\n\ from pycryptopp.hash import sha256"); @@ -69,4 +71,5 @@ init_pycryptopp(void) { init_sha256(module); init_aes(module); init_xsalsa20(module); + init_chacha20(module); } diff --git a/src/pycryptopp/cipher/__init__.py b/src/pycryptopp/cipher/__init__.py index 0ebfadf..319f6c3 100644 --- a/src/pycryptopp/cipher/__init__.py +++ b/src/pycryptopp/cipher/__init__.py @@ -1,4 +1,5 @@ import aes import xsalsa20 +import chacha20 -quiet_pyflakes=[aes, xsalsa20] +quiet_pyflakes=[aes, xsalsa20, chacha20] diff --git a/src/pycryptopp/cipher/chacha20.py b/src/pycryptopp/cipher/chacha20.py new file mode 100644 index 0000000..fd8359d --- /dev/null +++ b/src/pycryptopp/cipher/chacha20.py @@ -0,0 +1,31 @@ +from pycryptopp import _import_my_names + +_import_my_names(globals(), "chacha20_") + +del _import_my_names + +def selftest(): + # pyflakes doesn't know that Chacha20 is made available above + Chacha20 = globals()["ChaCha20"] + from binascii import unhexlify + key = unhexlify("ad5eadf7163b0d36e44c126037a03419" + "fcda2b3a1bb4ab064b6070e61b0fa5ca") + iv = unhexlify("6a059adb8c7d4acb1c537767d541506f" "c5ef0ace9a2a65bd") + encrypted = unhexlify("6c845801d0df33d8aa5ad8c8ff3ebfd5" + "9ab66b64f2157e8c6521e0c34ef0f233" + "baf02fa7a2c289d1b725905667696ac9" + "ba966d72b2d6cac601") + p = Chacha20(key, iv) + decrypted = p.process(encrypted) + expected = "crypto libraries should always test themselves at powerup" + assert decrypted == expected + + p = Chacha20(key, iv) + decrypted = "" + offset = 0 + for chunksize in [13,11,1,2,3,20,999]: + decrypted += p.process(encrypted[offset:offset+chunksize]) + offset += chunksize + assert decrypted == expected + +selftest() diff --git a/src/pycryptopp/cipher/chacha20module.cpp b/src/pycryptopp/cipher/chacha20module.cpp new file mode 100644 index 0000000..c6432a9 --- /dev/null +++ b/src/pycryptopp/cipher/chacha20module.cpp @@ -0,0 +1,180 @@ +/** + * chacha20module.cpp -- Python wrappers around Crypto++'s chacha20 + */ + +#define PY_SSIZE_T_CLEAN +#include +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +#include "chacha20module.hpp" + +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#else +#include +#endif + +static const char* const chacha20__doc__ = "_chacha20 cipher"; + +static PyObject *chacha20_error; + +typedef struct { + PyObject_HEAD + + /* internal */ + //CryptoPP::CTR_Mode::Encryption *e; + CryptoPP::ChaCha20::Encryption *e; +} ChaCha20; + +PyDoc_STRVAR(ChaCha20__doc__, +"An ChaCha20 cipher object.\n\ +\n\ +This object encrypts/decrypts in CTR mode, using a counter that is initialized\n\ +to zero when you instantiate the object. Successive calls to .process() will \n\ +use the current counter and increment it.\n\ +\n\ +"); + +static PyObject *ChaCha20_process(ChaCha20* self, PyObject* msgobj) { + if(!PyString_CheckExact(msgobj)) { + PyStringObject* typerepr = reinterpret_cast(PyObject_Repr(reinterpret_cast(msgobj->ob_type))); + if (typerepr) { + PyErr_Format(chacha20_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else), but you passed %s.", PyString_AS_STRING(reinterpret_cast(typerepr))); + Py_DECREF(typerepr); + } else + PyErr_Format(chacha20_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else)."); + return NULL; + } + + const char* msg; + Py_ssize_t msgsize; + if (PyString_AsStringAndSize(msgobj, const_cast(&msg), &msgsize)) + return NULL; + assert (msgsize >= 0); + + PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, msgsize)); + if (!result) + return NULL; + + self->e->ProcessString(reinterpret_cast(PyString_AS_STRING(result)), reinterpret_cast(msg), msgsize); + return reinterpret_cast(result); +} + +PyDoc_STRVAR(ChaCha20_process__doc__, +"Encrypt or decrypt the next bytes, returning the result."); + +static PyMethodDef ChaCha20_methods[] = { + {"process", reinterpret_cast(ChaCha20_process), METH_O, ChaCha20_process__doc__}, + {NULL}, +}; + +static PyObject* ChaCha20_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) { + ChaCha20* self = reinterpret_cast(type->tp_alloc(type, 0)); + if (!self) + return NULL; + self->e = NULL; + return reinterpret_cast(self); +} + +static void ChaCha20_dealloc(PyObject* self) { + if (reinterpret_cast(self)->e) + delete reinterpret_cast(self)->e; + self->ob_type->tp_free(self); +} + +static int ChaCha20_init(PyObject* self, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { "key", "iv", NULL}; + const char *key = NULL; + Py_ssize_t keysize = 0; + const char *iv = NULL; + const char defaultiv[24] = {0}; + Py_ssize_t ivsize = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#|t#:ChaCha20.__init__", const_cast(kwlist), &key, &keysize, &iv, &ivsize)) + return -1; + assert (keysize >= 0); + assert (ivsize >= 0); + + if (keysize != 32 && keysize != 16 ) { + PyErr_Format(chacha20_error, "Precondition violation: key must be exactly 32 or 16 bytes, not %d", keysize); + return -1; + } + if (!iv) + iv = defaultiv; + else if (ivsize != 24) { + PyErr_Format(chacha20_error, "Precondition violation: if an IV is passed, it must be exactly 24 bytes, not %d", ivsize); + return -1; + } + + try { + reinterpret_cast(self)->e = new CryptoPP::ChaCha20::Encryption(reinterpret_cast(key), keysize, reinterpret_cast(iv)); + } + catch (CryptoPP::InvalidKeyLength le) + { + PyErr_Format(chacha20_error, "Precondition violation: you are required to pass a valid key size. Crypto++ gave this exception: %s", le.what()); + return -1; + } + if (!reinterpret_cast(self)->e) + { + PyErr_NoMemory(); + return -1; + } + return 0; +} + + +static PyTypeObject ChaCha20_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "_chacha20.ChaCha20", /*tp_name*/ + sizeof(ChaCha20), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + ChaCha20_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + ChaCha20__doc__, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + ChaCha20_methods, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + ChaCha20_init, /*tp_init*/ + 0, /*tp_alloc*/ + ChaCha20_new, /*tp_new*/ +}; + +void init_chacha20(PyObject*const module) +{ + if (PyType_Ready(&ChaCha20_type) < 0) + return; + Py_INCREF(&ChaCha20_type); + PyModule_AddObject(module, "chacha20_ChaCha20", (PyObject *)&ChaCha20_type); + + chacha20_error = PyErr_NewException(const_cast("_chacha20.Error"), NULL, NULL); + PyModule_AddObject(module, "chacha20_Error", chacha20_error); + + PyModule_AddStringConstant(module, "chacha20__doc__", const_cast(chacha20__doc__)); +} diff --git a/src/pycryptopp/cipher/chacha20module.hpp b/src/pycryptopp/cipher/chacha20module.hpp new file mode 100644 index 0000000..a2c61a3 --- /dev/null +++ b/src/pycryptopp/cipher/chacha20module.hpp @@ -0,0 +1,6 @@ +#ifndef __INCL_CHACHA20MODULE_HPP +#define __INCL_CHACHA20MODULE_HPP + +extern void init_chacha20(PyObject* module); + +#endif; /*#ifndef __INCL_CHACHA20MODULE_HPP*/ diff --git a/src/pycryptopp/test/test_chacha20.py b/src/pycryptopp/test/test_chacha20.py new file mode 100644 index 0000000..a0c019b --- /dev/null +++ b/src/pycryptopp/test/test_chacha20.py @@ -0,0 +1,132 @@ +import random, re +import unittest + +from binascii import a2b_hex, b2a_hex +from pkg_resources import resource_string + +from pycryptopp.cipher import chacha20 +TEST_XSALSA_RE=re.compile("\nCOUNT=([0-9]+)\nKEY=([0-9a-f]+)\nIV=([0-9a-f]+)\nPLAINTEXT=([0-9a-f]+)\nCIPHERTEXT=([0-9a-f]+)") + +class ChaCha20Test(unittest.TestCase): + + enc0="20b800ca9a9247bcc09a6816b123be47ac0681e23749d35fea22c04e1b1b9bb19782ab297a65c80ab1bac2ff2c4beba4c807bf832fdb57e648b3b677d87f8758123fb0f9d39efa95d7dd3f72fb0abe9b96e68514e758e9de31ae1d694c462de537f7e45188f2dcb912c6a0ed1aee5f6b4d2be8c3a1126e928b6fea91d643f9bbe808d984c2517bcb928161" + + def test_zero_ChaCha20(self): + key="1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389" + iv="69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37" + computedcipher=chacha20.ChaCha20(a2b_hex(key),a2b_hex(iv)).process('\x00'*139) + self.failUnlessEqual(a2b_hex(self.enc0), computedcipher, "enc0: %s, computedciper: %s" % (self.enc0, b2a_hex(computedcipher))) + + cryptor=chacha20.ChaCha20(a2b_hex(key),a2b_hex(iv)) + + computedcipher1=cryptor.process('\x00'*69) + computedcipher2=cryptor.process('\x00'*69) + computedcipher3=cryptor.process('\x00') + computedcipher12=b2a_hex(computedcipher1)+b2a_hex(computedcipher2)+b2a_hex(computedcipher3) + self.failUnlessEqual(self.enc0, computedcipher12) + + + def test_ChaCha20(self): + # The test vector is from Crypto++'s TestVectors/chacha.txt, comment + # there is: Source: created by Wei Dai using naclcrypto-20090308 . + # naclcrypto being DJB's crypto library and of course DJB designed + # ChaCha20 + s = resource_string("pycryptopp", "testvectors/chacha.txt") + return self._test_ChaCha20(s) + + def _test_ChaCha20(self, vects_str): + for mo in TEST_XSALSA_RE.finditer(vects_str): + #count = int(mo.group(1)) + key = a2b_hex(mo.group(2)) + iv = a2b_hex(mo.group(3)) + #plaintext = a2b_hex(mo.group(4)) + #ciphertext= a2b_hex(mo.group(5)) + plaintext = mo.group(4) + ciphertext = mo.group(5) + computedcipher=chacha20.ChaCha20(key,iv).process(a2b_hex(plaintext)) + #print "ciphertext", b2a_hex(computedcipher), '\n' + #print "computedtext", ciphertext, '\n' + #print count, ": \n" + self.failUnlessEqual(computedcipher,a2b_hex(ciphertext),"computedcipher: %s, ciphertext: %s" % (b2a_hex(computedcipher), ciphertext)) + + #the random decomposing + plaintext1 = "" + plaintext2 = "" + length = len(plaintext) + rccipher = "" + cryptor = chacha20.ChaCha20(key,iv) + if length > 2: + point = random.randint(0,length-3) + if (point%2) !=0: + point -= 1 + plaintext1 += plaintext[:point+2] + plaintext2 += plaintext[point+2:] + rccipher += b2a_hex(cryptor.process(a2b_hex(plaintext1))) + rccipher += b2a_hex(cryptor.process(a2b_hex(plaintext2))) + self.failUnlessEqual(rccipher, ciphertext, "random computed cipher: %s, ciphertext: %s" % (rccipher, ciphertext)) + + #every byte encrypted + cryptor = chacha20.ChaCha20(key,iv) + eccipher="" + l = 0 + while l<=(length-2): + eccipher += b2a_hex(cryptor.process(a2b_hex(plaintext[l:l+2]))) + l += 2 + self.failUnlessEqual(eccipher, ciphertext, "every byte computed cipher: %s, ciphertext: %s" % (eccipher, ciphertext)) + + + def test_types_and_lengths(self): + + # the key= argument must be a bytestring exactly 32 bytes long + self.failUnlessRaises(TypeError, chacha20.ChaCha20, None) + for i in range(70): + key = "a"*i + if i != 32 and i != 16: + self.failUnlessRaises(chacha20.Error, chacha20.ChaCha20, key) + else: + self.failUnless(chacha20.ChaCha20(key)) + + # likewise, iv= (if provided) must be exactly 24 bytes long. Passing + # None is not treated the same as not passing the argument at all. + key = "a"*32 + self.failUnlessRaises(TypeError, chacha20.ChaCha20, key, None) + for i in range(70): + iv = "i"*i + if i != 24: + self.failUnlessRaises(chacha20.Error, chacha20.ChaCha20, key, iv) + else: + self.failUnless(chacha20.ChaCha20(key, iv)) + + def test_recursive(self): + # Try to use the same technique as: + # http://blogs.msdn.com/si_team/archive/2006/05/19/aes-test-vectors.aspx + # It's not exactly the same, though, because ChaCha20 is a stream + # cipher, whereas the Ferguson code is exercising a block cipher. But + # we try to do something similar. + + # the ChaCha20 internal function uses a 32-byte block. We want to + # exercise it twice for each key, to guard against + # clobbering-after-key-setup errors. Just doing enc(enc(p)) could let + # XOR errors slip through. So to be safe, use B=64. + B=64 + N=24 + K=32 + s = "\x00"*(B+N+K) + def enc(key, nonce, plaintext): + p = chacha20.ChaCha20(key=key, iv=nonce) + return p.process(plaintext) + for i in range(1000): + plaintext = s[-K-N-B:-K-N] + nonce = s[-K-N:-K] + key = s[-K:] + ciphertext = enc(key, nonce, plaintext) + s += ciphertext + s = s[-K-N-B:] + output = b2a_hex(s[-B:]) + # I compared test output against pysodium - David + self.failUnlessEqual(output, "2a84ffcd163b683daafd51b2d10af7338ac5fb25716d5f7b6e6af9cdbe6abd6e63c00d4e8eff8c306b17d71691b6ce1e6e0577c0e8e719abb3dfa7f7b21d955e") + + + +if __name__ == "__main__": + unittest.main() diff --git a/src/pycryptopp/testvectors/chacha.txt b/src/pycryptopp/testvectors/chacha.txt new file mode 100644 index 0000000..18ed115 --- /dev/null +++ b/src/pycryptopp/testvectors/chacha.txt @@ -0,0 +1,120 @@ +AlgorithmType: SymmetricCipher +Name: ChaCha8 +Source: http://tools.ietf.org/html/draft-strombergson-chacha-test-vectors +Comment: TC1 - All zero key and IV (16-byte key). +Key: r16 00 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: e28a5fa4a67f8c5defed3e6fb7303486aa8427d31419a729572d777953491120b64ab8e72b8deb85cd6aea7cb6089a101824beeb08814a428aab1fa2c816081b +Test: Encrypt +Comment: TC1 - All zero key and IV (32-byte key). +Key: r32 00 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: 3e00ef2f895f40d67f5bb8e81f09a5a12c840ec3ce9a7f3b181be188ef711a1e984ce172b9216f419f445367456d5619314a42a3da86b001387bfdb80e0cfe42 +Test: Encrypt +Comment: TC2 - Single bit in key set. All zero IV (16-byte key). +Key: 0x01000000000000000000000000000000 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: 03a7669888605a0765e8357475e58673f94fc8161da76c2a3aa2f3caf9fe5449e0fcf38eb882656af83d430d410927d55c972ac4c92ab9da3713e19f761eaa14 +Test: Encrypt +Comment: TC2 - Single bit in key set. All zero IV (32-byte key). +Key: 0x0100000000000000000000000000000000000000000000000000000000000000 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: cf5ee9a0494aa9613e05d5ed725b804b12f4a465ee635acc3a311de8740489ea289d04f43c7518db56eb4433e498a1238cd8464d3763ddbb9222ee3bd8fae3c8 +Test: Encrypt +Comment: TC3 - Single bit in IV set. All zero key (16-byte key). +Key: r16 00 +IV: 0x0100000000000000 +Plaintext: r64 00 +Ciphertext: 25f5bec6683916ff44bccd12d102e692176663f4cac53e719509ca74b6b2eec85da4236fb29902012adc8f0d86c8187d25cd1c486966930d0204c4ee88a6ab35 +Test: Encrypt +Comment: TC3 - Single bit in IV set. All zero key (32-byte key). +Key: r32 00 +IV: 0x0100000000000000 +Plaintext: r64 00 +Ciphertext: 2b8f4bb3798306ca5130d47c4f8d4ed13aa0edccc1be6942090faeeca0d7599b7ff0fe616bb25aa0153ad6fdc88b954903c22426d478b97b22b8f9b1db00cf06 +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: ChaCha12 +Source: http://tools.ietf.org/html/draft-strombergson-chacha-test-vectors +Comment: TC1 - All zero key and IV (16-byte key). +Key: r16 00 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: e1047ba9476bf8ff312c01b4345a7d8ca5792b0ad467313f1dc412b5fdce32410dea8b68bd774c36a920f092a04d3f95274fbeff97bc8491fcef37f85970b450 +Test: Encrypt +Comment: TC1 - All zero key and IV (32-byte key). +Key: r32 00 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: 9bf49a6a0755f953811fce125f2683d50429c3bb49e074147e0089a52eae155f0564f879d27ae3c02ce82834acfa8c793a629f2ca0de6919610be82f411326be +Test: Encrypt +Comment: TC2 - Single bit in key set. All zero IV (16-byte key). +Key: 0x01000000000000000000000000000000 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: 2a865a3b8999fa83ae8aacf33fc6be4f32c8aa9762738d26963270052f4eef8b86af758f7867560af6d0eeb973b5542bb24c8abceac8b1f36d026963d6c8a9b2 +Test: Encrypt +Comment: TC2 - Single bit in key set. All zero IV (32-byte key). +Key: 0x0100000000000000000000000000000000000000000000000000000000000000 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: 12056e595d56b0f6eef090f0cd25a20949248c2790525d0f930218ff0b4ddd10a6002239d9a454e29e107a7d06fefdfef0210feba044f9f29b1772c960dc29c0 +Test: Encrypt +Comment: TC3 - Single bit in IV set. All zero key (16-byte key). +Key: r16 00 +IV: 0x0100000000000000 +Plaintext: r64 00 +Ciphertext: 91cdb2f180bc89cfe86b8b6871cd6b3af61abf6eba01635db619c40a0b2e19edfa8ce5a9bd7f53cc2c9bcfea181e9754a9e245731f658cc282c2ae1cab1ae02c +Test: Encrypt +Comment: TC3 - Single bit in IV set. All zero key (32-byte key). +Key: r32 00 +IV: 0x0100000000000000 +Plaintext: r64 00 +Ciphertext: 64b8bdf87b828c4b6dbaf7ef698de03df8b33f635714418f9836ade59be1296946c953a0f38ecffc9ecb98e81d5d99a5edfc8f9a0a45b9e41ef3b31f028f1d0f +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: ChaCha20 +Source: http://tools.ietf.org/html/draft-strombergson-chacha-test-vectors +Comment: TC1 - All zero key and IV (16-byte key). +Key: r16 00 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: 89670952608364fd00b2f90936f031c8e756e15dba04b8493d00429259b20f46cc04f111246b6c2ce066be3bfb32d9aa0fddfbc12123d4b9e44f34dca05a103f +Test: Encrypt +Comment: TC1 - All zero key and IV (32-byte key). +Key: r32 00 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: 76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586 +Test: Encrypt +Comment: TC2 - Single bit in key set. All zero IV (16-byte key). +Key: 0x01000000000000000000000000000000 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: ae56060d04f5b597897ff2af1388dbceff5a2a4920335dc17a3cb1b1b10fbe70ece8f4864d8c7cdf0076453a8291c7dbeb3aa9c9d10e8ca36be4449376ed7c42 +Test: Encrypt +Comment: TC2 - Single bit in key set. All zero IV (32-byte key). +Key: 0x0100000000000000000000000000000000000000000000000000000000000000 +IV: r8 00 +Plaintext: r64 00 +Ciphertext: c5d30a7ce1ec119378c84f487d775a8542f13ece238a9455e8229e888de85bbd29eb63d0a17a5b999b52da22be4023eb07620a54f6fa6ad8737b71eb0464dac0 +Test: Encrypt +Comment: TC3 - Single bit in IV set. All zero key (16-byte key). +Key: r16 00 +IV: 0x0100000000000000 +Plaintext: r64 00 +Ciphertext: 1663879eb3f2c9949e2388caa343d361bb132771245ae6d027ca9cb010dc1fa7178dc41f8278bc1f64b3f12769a24097f40d63a86366bdb36ac08abe60c07fe8 +Test: Encrypt +Comment: TC3 - Single bit in IV set. All zero key (32-byte key). +Key: r32 00 +IV: 0x0100000000000000 +Plaintext: r64 00 +Ciphertext: ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b +Test: Encrypt +