def test_block_oriented(self): """ Test usage of block oriented encrypt/decrypt for large files. """ key = to_octets(""" 00 01 00 00 00 00 00 00 00 ff 00 00 00 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 """) nonce = to_octets(""" 01 02 03 00 00 00 00 00 00 00 00 00 """) # test various sizes of plain text to validate blocking for pt_size in (0, 1, 63, 64, 65, 127, 128, 129, 130): pt = ''.join([chr(i) for i in range(pt_size)]) nonce = 'aaaaaaaaaaaa' chacha=ChaCha(key, nonce=nonce) b_size = ChaCha.block_size # this would typically be performed by reading file blocks blocks, remainder = divmod( len(pt), ChaCha.block_size ) ct = '' for j in range(blocks): ct += chacha.encrypt( pt[j*b_size:(j+1)*b_size] ) ct += chacha.encrypt( pt[blocks*b_size:] ) # reuse nonce to test block oriented encryption chacha = ChaCha(key, nonce=nonce) ct2 = chacha.encrypt( pt ) self.assertEqual(ct, ct2) # block oriented and full msg encrypt compare
def validate_test_vectors(): """ Create new ChaCha instance, encrypt and decrypt test vectors """ chacha = ChaCha(key, counter=initial_block_counter, nonce=nonce) ct = chacha.encrypt( plain_text ) self.assertEqual( ct, cipher_text ) # validate encryption chacha = ChaCha(key, counter=initial_block_counter, nonce=nonce) pt = chacha.decrypt( cipher_text ) self.assertEqual( pt, plain_text ) # validate decryption
def test_nonce_api(self): """ Tests of nonce usage """ key = to_octets(""" 00 01 00 00 00 00 00 00 00 ff 00 00 00 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 """) nonce = to_octets(""" 01 02 03 00 00 00 00 00 00 00 00 00 """) plain_text = 11*"""API related test""" chacha = ChaCha(key, nonce=nonce) ct1 = chacha.encrypt( plain_text ) chacha = ChaCha(key, nonce=nonce) pt1 = chacha.decrypt( ct1 ) # .... ct2= chacha.encrypt( plain_text ) chacha=ChaCha(key) # auto generation of nonce # retrieve nonce for testing nonce = pack( '<III', chacha.state[13], chacha.state[14], chacha.state[15]) ct2 = chacha.encrypt( plain_text ) self.assertNotEqual(ct1, ct2) chacha = ChaCha( key, nonce=nonce ) pt2 = chacha.decrypt( ct2 ) self.assertEqual( pt1, pt2 )
def test_block_oriented(self): """ Test usage of block oriented encrypt/decrypt for large files. """ key = to_octets(""" 00 01 00 00 00 00 00 00 00 ff 00 00 00 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 """) nonce = to_octets(""" 01 02 03 00 00 00 00 00 00 00 00 00 """) # test various sizes of plain text to validate blocking for pt_size in (0, 1, 63, 64, 65, 127, 128, 129, 130): pt = ''.join([chr(i) for i in range(pt_size)]) nonce = 'aaaaaaaaaaaa' chacha = ChaCha(key, nonce=nonce) b_size = ChaCha.block_size # this would typically be performed by reading file blocks blocks, remainder = divmod(len(pt), ChaCha.block_size) ct = '' for j in range(blocks): ct += chacha.encrypt(pt[j * b_size:(j + 1) * b_size]) ct += chacha.encrypt(pt[blocks * b_size:]) # reuse nonce to test block oriented encryption chacha = ChaCha(key, nonce=nonce) ct2 = chacha.encrypt(pt) self.assertEqual(ct, ct2) # block oriented and full msg encrypt compare
def validate_test_vectors(): """ Create new ChaCha instance, encrypt and decrypt test vectors """ chacha = ChaCha(key, counter=initial_block_counter, nonce=nonce) ct = chacha.encrypt(plain_text) self.assertEqual(ct, cipher_text) # validate encryption chacha = ChaCha(key, counter=initial_block_counter, nonce=nonce) pt = chacha.decrypt(cipher_text) self.assertEqual(pt, plain_text) # validate decryption
def test_vector_for_the_ChaCha20_block_function(self): """ 2.3.2. Test Vector for the ChaCha20 Block Function For a test vector, we will use the following inputs to the ChaCha20 block function: """ key = to_octets(""" 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f: 10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f """) nonce = to_octets(""" 00:00:00:09:00:00:00:4a:00:00:00:00 """) block_counter = 1 """ After setting up the ChaCha state, it looks like this: ChaCha state with the key setup. """ e_state = (0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x00000001, 0x09000000, 0x4a000000, 0x00000000) # validate ChaCha key setup chacha = ChaCha(key, counter=block_counter, nonce=nonce) for expected, calculated in zip(e_state, chacha.state): self.assertEqual(expected, calculated) """ After running 20 rounds (10 column rounds interleaved with 10 "diagonal rounds"), the ChaCha state looks like this: ChaCha state after 20 rounds """ e_state = (0x837778ab, 0xe238d763, 0xa67ae21e, 0x5950bb2f, 0xc4f2d0c7, 0xfc62bb2f, 0x8fa018fc, 0x3f5ec7b7, 0x335271c2, 0xf29489f3, 0xeabda8fc, 0x82e46ebd, 0xd19c12b4, 0xb04e16de, 0x9e83d0cb, 0x4e3c50a2) # test of inner block calculations test_state = list(chacha.state) # copy state for i in range(10): inner_block(test_state) for expected, calculated in zip(e_state, test_state): self.assertEqual(expected, calculated) """
def test_random_nonce(self): """ Tests of nonce usage """ key = to_octets(""" 00 01 00 00 00 00 00 00 00 ff 00 00 00 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 """) plain_text = 11 * """Random nonce test""" n_dict = {} for i in range(100000): chacha = ChaCha(key) # auto generation of nonce # retrieve nonce for testing nonce = pack('<III', chacha.state[13], chacha.state[14], chacha.state[15]) if nonce in n_dict: raise ValueError("urandom generated duplicate nonce") else: n_dict[nonce] = True
def test_nonce_api(self): """ Tests of nonce usage """ key = to_octets(""" 00 01 00 00 00 00 00 00 00 ff 00 00 00 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 """) nonce = to_octets(""" 01 02 03 00 00 00 00 00 00 00 00 00 """) plain_text = 11 * """API related test""" chacha = ChaCha(key, nonce=nonce) ct1 = chacha.encrypt(plain_text) chacha = ChaCha(key, nonce=nonce) pt1 = chacha.decrypt(ct1) # .... ct2 = chacha.encrypt(plain_text) chacha = ChaCha(key) # auto generation of nonce # retrieve nonce for testing nonce = pack('<III', chacha.state[13], chacha.state[14], chacha.state[15]) ct2 = chacha.encrypt(plain_text) self.assertNotEqual(ct1, ct2) chacha = ChaCha(key, nonce=nonce) pt2 = chacha.decrypt(ct2) self.assertEqual(pt1, pt2)
def test_nonce_api(self): """ Tests of nonce usage and detection of nonce reuse""" key = to_octets(""" 00 01 00 00 00 00 00 00 00 ff 00 00 00 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 """) nonce = to_octets(""" 01 02 03 00 00 00 00 00 00 00 00 00 """) plain_text = 11 * """API related test""" chacha = ChaCha(key, nonce=nonce) ct1 = chacha.encrypt(plain_text) chacha = ChaCha(key, nonce=nonce) pt1 = chacha.decrypt(ct1) # check for error on second use of the manually set nonce self.assertRaises(ValueError, chacha.encrypt, plain_text) chacha = ChaCha(key) # auto generation of nonce ct2 = chacha.encrypt(plain_text) self.assertNotEqual(ct1, ct2) nonce = chacha.nonce # retrieve nonce from prior usage chacha = ChaCha(key, nonce=nonce) pt2 = chacha.decrypt(ct2) self.assertEqual(pt1, pt2)