def _run_test(self, key1, key2, plaintext, tweak, expected_ciphertext): rij1 = Rijndael(key1) rij2 = Rijndael(key2) xts = XTS(rij1, rij2.encrypt) ciphertext = xts.encrypt(plaintext, tweak) self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(xts.decrypt(ciphertext, tweak), plaintext)
def _run_test(self, key, plaintext, block_size, test_vector, iterations=1): rijndael = Rijndael(key, block_size=block_size) to_enc = plaintext for _ in range(iterations): to_enc = rijndael.encrypt(to_enc) cipherhex = codecs.encode(to_enc, 'hex_codec') self.assertEqual(cipherhex, test_vector) to_dec = to_enc for _ in range(iterations): to_dec = rijndael.decrypt(to_dec) self.assertEqual(plaintext, to_dec)
def test_all_vecs(self): for unparsed_vec in TEST_VECS: _alg, key, nonce, plaintext, ciphertext, _what = unparsed_vec.split(":") key_bytes, nonce, plaintext, expected_ciphertext = [codecs.decode(item.encode('utf-8'), 'hex_codec') for item in [key, nonce, plaintext, ciphertext]] key = Bytes(key_bytes).zfill(ceil(len(key_bytes) / 16) * 16) ctr = CTR(Rijndael(key), nonce[:15]) ctr.counter = 1 ciphertext = ctr.encrypt(plaintext) ctr = CTR(Rijndael(key), nonce[:15]) ctr.counter = 1 self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(plaintext, ctr.decrypt(ciphertext))
def _run_test(self, key, plaintext, expected_ciphertext): rij = Rijndael(key) ecb = ECB(rij) ciphertext = ecb.encrypt(plaintext, pad=False) self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(ecb.decrypt(ciphertext, unpad=False), plaintext)
def _run_test(self, key, iv, plaintext, expected_ciphertext): rij = Rijndael(key) cbc = CBC(rij, iv=iv) ciphertext = cbc.encrypt(plaintext, pad=False) self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(cbc.decrypt(ciphertext, unpad=False), plaintext)
def _run_test(self, key, plaintext, nonce, header, expected_ciphertext): rij = Rijndael(key) eax = EAX(rij, nonce) ciphertext = eax.encrypt(plaintext, header) self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(eax.decrypt(ciphertext, header), plaintext)
def _run_test(self, key, plaintext, nonce, auth_data, expected_tag, expected_ciphertext): rij = Rijndael(key) ocb2 = OCB2(rij) ciphertext = ocb2.encrypt(nonce, plaintext, auth_data) self.assertEqual(ciphertext, (expected_tag, expected_ciphertext)) self.assertEqual(ocb2.decrypt(nonce, ciphertext, auth_data), plaintext)
def _run_test(self, plaintext, expected_ciphertext): rij = Rijndael(0x636869636b656e207465726979616b69) cts = CBCCTS(rij, iv=b'\x00' * 16) ciphertext = cts.encrypt(plaintext) self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(cts.decrypt(ciphertext), plaintext)
def _run_test(self, key, iv, plaintext, expected_ciphertext): rij = Rijndael(key) cfb = CFB(rij, iv) ciphertext = cfb.encrypt(plaintext) self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(cfb.decrypt(ciphertext), plaintext)
def decrypt(self, kek: bytes, encrypted_key: bytes, header: dict) -> Bytes: rij = Rijndael(kek) gcm = GCM(rij) return gcm.decrypt( url_b64_decode(header['iv'].encode('utf-8')), encrypted_key + url_b64_decode(header['tag'].encode('utf-8')), b'')
def __init__(self, cipher: EncryptionAlg = None, iv: bytes = b'\x00' * 16): """ Parameters: cipher (EncryptionAlg): Instantiated encryption algorithm. iv (bytes): Initialization vector. """ self.cmac = CMAC(cipher or Rijndael(Bytes.random(32))) self.iv = iv
def __init__(self, cipher: EncryptionAlg=None, iv: bytes=b'\x00' * 16): """ Parameters: cipher (EncryptionAlg): Instantiated encryption algorithm. iv (bytes): Initialization vector for CBC mode. """ Primitive.__init__(self) self.cbc = CBC(cipher or Rijndael(Bytes.random(32)), iv)
def _run_test(self, rij_key, siv_key, plaintext, additional_data, expected_ciphertext): rij = Rijndael(rij_key) siv = SIV(siv_key, rij) ciphertext = siv.encrypt(plaintext, additional_data) self.assertEqual(ciphertext, expected_ciphertext) self.assertEqual(siv.decrypt(ciphertext, additional_data), plaintext)
def encrypt_and_auth(self, key: bytes, iv: bytes, plaintext: bytes, auth_data: bytes) -> (Bytes, Bytes): rij = Rijndael(key) gcm = GCM(rij) ct_and_tag = gcm.encrypt(iv, plaintext, auth_data) return ct_and_tag[:-16], ct_and_tag[-16:]
def encrypt(self, kek: bytes, cek: bytes, header: dict) -> Bytes: rij = Rijndael(kek) gcm = GCM(rij) ct_and_tag = gcm.encrypt(url_b64_decode(header['iv'].encode('utf-8')), cek, b'') header['tag'] = url_b64_encode(ct_and_tag[-16:]).decode() return ct_and_tag[:-16]
def test_gauntlet(self): rij = Rijndael(Bytes(0x0).zfill(32)) cts = ECBCTS(rij) for _ in range(100): plaintext = Bytes.random(Bytes.random(1).int() + 17) if len(plaintext) < 17: plaintext = plaintext.zfill(17) ciphertext = cts.encrypt(plaintext) self.assertEqual(cts.decrypt(ciphertext), plaintext)
def test_all_vecs(self): for key, nonce, data, size, plaintext, expected_ciphertext in TEST_VECTORS: key = Bytes(key) nonce = Bytes(nonce) data = Bytes(data) data = data.zfill(len(data) + 1) plaintext = Bytes(plaintext) ccm = CCM(Rijndael(key), size) ciphertext = ccm.encrypt(nonce, plaintext, data) self.assertEqual(ciphertext, Bytes(expected_ciphertext)) self.assertEqual(ccm.decrypt(nonce, ciphertext, data), plaintext)
def __run_test(self, kek, cek, expected_wrapping, iv=KW.RFC3394_IV, pad=False): rij = Rijndael(kek) kw = KW(rij, iv=iv) wrapped_key = kw.encrypt(cek, pad=pad) self.assertEqual(wrapped_key, expected_wrapping) self.assertEqual(kw.decrypt(wrapped_key, unpad=pad), cek)
def test_equivalence_attack(self): plaintext = b'-Super secret message! Hope no one cracks this!-' ciphertext = sender_encrypt(plaintext) attack = CBCIVKeyEquivalenceAttack(self, 16) key_iv = bytes(attack.execute(ciphertext)) self.assertEqual(key_iv, key) recovered_plaintext = CBC(Rijndael(key), key_iv).decrypt(bytes(ciphertext)) print(recovered_plaintext) self.assertEqual(plaintext, recovered_plaintext)
def test_zfill(self): cipher_obj = Rijndael(Bytes(0x8000000000000000).zfill(16)) plaintext = Bytes(b'').zfill(16) ciphertext1 = cipher_obj.encrypt(plaintext) ciphertext2 = cipher_obj.decrypt(plaintext) self.assertEqual(cipher_obj.decrypt(ciphertext1), plaintext) self.assertEqual(cipher_obj.encrypt(ciphertext2), plaintext)
def encrypt_and_auth(self, key: bytes, iv: bytes, plaintext: bytes, auth_data: bytes) -> (Bytes, Bytes): mac_key, enc_key = key.chunk(self.chunk_size) rij = Rijndael(enc_key) cbc = CBC(rij, iv=iv) ciphertext = cbc.encrypt(plaintext) hmac = HMAC( mac_key, self.hash_obj).generate(auth_data + iv + ciphertext + Bytes(len(auth_data) * 8).zfill(8))[:self.chunk_size] return ciphertext, hmac
def test_all_vecs(self): for unparsed_vec in TEST_VECS: _alg, key, nonce, plaintext, ciphertext, data, tag = unparsed_vec.split( ":") key_bytes, nonce, plaintext, expected_ciphertext, data, expected_tag = [ codecs.decode(item.encode('utf-8'), 'hex_codec') for item in [key, nonce, plaintext, ciphertext, data, tag] ] key = Bytes(key_bytes).zfill(len(key_bytes)) gcm = GCM(Rijndael(key)) authed_ct = gcm.encrypt(Bytes(nonce), Bytes(plaintext), data) self.assertEqual(authed_ct[:-16], expected_ciphertext) self.assertEqual(authed_ct[-16:], expected_tag) self.assertEqual(plaintext, gcm.decrypt(nonce, authed_ct, data))
def decrypt(self, key: bytes, iv: bytes, ciphertext: bytes, auth_data: bytes, auth_tag: bytes) -> Bytes: mac_key, enc_key = key.chunk(self.chunk_size) hmac = HMAC( mac_key, self.hash_obj).generate(auth_data + iv + ciphertext + Bytes(len(auth_data) * 8).zfill(8))[:self.chunk_size] assert RUNTIME.compare_bytes(hmac, auth_tag) rij = Rijndael(enc_key) cbc = CBC(rij, iv=iv) return cbc.decrypt(ciphertext)
def test_gauntlet(self): for _ in range(100): plaintext = Bytes.random(16) rij = Rijndael(Bytes.random(16)) ocb = OCB2(rij) nonce = Bytes.random(16) def oracle_func(plaintext, data): return ocb.encrypt(nonce, plaintext, data) attack = OCBAuthForgeryAttack(ChosenPlaintextOracle(oracle_func)) tag, ct = attack.execute(plaintext) # OCB2 will automatically verify and throw an AssertException if the tag is incorrect ocb.decrypt(nonce, (tag, ct), verify=True)
def test(self): rij = Rijndael(Bytes.random(32)) gcm = GCM(rij) nonce = Bytes.random(12) ad_a = Bytes.random(8) ad_b = Bytes.random(24) pt_a = Bytes.random(16) pt_b = Bytes.random(16) ciphertext_a = gcm.encrypt(plaintext=pt_a, nonce=nonce, data=ad_a) ciphertext_b = gcm.encrypt(plaintext=pt_b, nonce=nonce, data=ad_b) ciphertext_a, tag_a = ciphertext_a[:-16], ciphertext_a[-16:] ciphertext_b, tag_b = ciphertext_b[:-16], ciphertext_b[-16:] attack = ForbiddenAttack() candidates = attack.execute(ad_a, ciphertext_a, tag_a, ad_b, ciphertext_b, tag_b) self.assertTrue(gcm.H in candidates)
from samson.block_ciphers.rijndael import Rijndael from samson.block_ciphers.modes.cbc import CBC from samson.attacks.cbc_iv_key_equivalence_attack import CBCIVKeyEquivalenceAttack import base64 import unittest import logging logging.basicConfig( format='%(asctime)s - %(name)s [%(levelname)s] %(message)s', level=logging.DEBUG) key_size = 16 key = rand_bytes(key_size) iv = key aes = Rijndael(key) cbc = CBC(aes, iv) def sender_encrypt(data): return cbc.encrypt(data) def receiver_decrypt(ciphertext): plaintext = cbc.decrypt(ciphertext, unpad=False) if any(int(byte) > 127 for byte in plaintext): raise Exception('Bad characters in {}'.format( base64.b64encode(plaintext))) class CBCIVEquivalenceTestCase(unittest.TestCase):
def compressor(message, state): return bytes( ECB(Rijndael(stretch_key(state, key_size))).encrypt(message)[:hash_size])
def decrypt(self, kek: bytes, encrypted_key: bytes, header: dict) -> Bytes: rij = Rijndael(kek) kw = KW(rij, iv=KW.RFC3394_IV) return kw.decrypt(encrypted_key)
def encrypt(self, kek: bytes, cek: bytes, header: dict) -> Bytes: rij = Rijndael(kek) kw = KW(rij, iv=KW.RFC3394_IV) return kw.encrypt(cek)
def decrypt(self, key: bytes, iv: bytes, ciphertext: bytes, auth_data: bytes, auth_tag: bytes) -> Bytes: rij = Rijndael(key) gcm = GCM(rij) return gcm.decrypt(iv, ciphertext + auth_tag, auth_data)