From 08b5d5fe577bb8afc95c3902ab8024691bdb282c Mon Sep 17 00:00:00 2001 From: cyfraeviolae Date: Fri, 26 Aug 2022 21:58:25 -0400 Subject: speedup --- aesgcmanalysis.py | 57 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/aesgcmanalysis.py b/aesgcmanalysis.py index 52b4012..4b7e32c 100644 --- a/aesgcmanalysis.py +++ b/aesgcmanalysis.py @@ -1,5 +1,7 @@ import random, struct, hmac, itertools, math from Crypto.Cipher import AES +import cryptography +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes import numpy as np ## Computation in GF(2^128)/(x^128 + x^7 + x^2 + x^1 + 1) @@ -609,8 +611,11 @@ def gen_blocks(n, js): return blocks squarer = np.array(Ms()) -matsqlookup = np.load(open('squares.np', 'rb')) adlookup = np.load(open('ad.np', 'rb')) +mcsqlookup = np.load(open('square_basis.np', 'rb')) + +def mc_squared(c, j): + return sum(mcsqlookup[i, j] for i in range(128) if 1 == (c >> i) & 1) % 2 def gen_ad(blocks): matret = np.zeros((128, 128)) @@ -621,12 +626,11 @@ def gen_ad(blocks): j = i + 1 # first is taken up by length block mat = None d = bytes_to_gf128(block) - matd = Mc(d) - if len(matsqlookup) > j: - matsq = matsqlookup[j] - else: + try: + mat = mc_squared(d, j) + except IndexError: matsq = np.linalg.matrix_power(squarer, j) % 2 - mat = matd @ matsq + mat = Mc(d) @ matsq matret += mat return matret % 2 # Because the elements of Ad are in GF2 we can mod 2 @@ -666,10 +670,11 @@ def chunk(xs, n=16): return [xs[i*n:(i+1)*n] for i in range(len(xs)//16)] def find_b(n, basis, ct, mac, nonce, aad, oracle): + orig_base = bytearray(ct).copy() base = bytearray(ct) idx = 0 while True: - choice = random.sample(basis, random.randint(1, 14)) + choice = random.sample(basis, random.randint(1, 10)) b = sum(choice) % 2 flips = gen_flips(b) blocks = gen_blocks(n, flips) @@ -679,11 +684,8 @@ def find_b(n, basis, ct, mac, nonce, aad, oracle): try: oracle(base[len(aad):], base[:len(aad)], mac, nonce) return b - except ValueError as e: - assert str(e) == 'MAC check failed' - for i, block in enumerate(chunk(blocks)): - j = (len(base)//16)-(2**(i+1)-1) - base[j*16:(j+1)*16] = xor(base[j*16:(j+1)*16], block) + except (cryptography.exceptions.InvalidTag, ValueError): + base = orig_base.copy() idx += 1 def nonce_truncation_recover_secrets(ct, mac, nonce, mac_bytes, aad, oracle, compute_T_once=False): @@ -722,7 +724,7 @@ def nonce_truncation_recover_secrets(ct, mac, nonce, mac_bytes, aad, oracle, com _, _, basisKerK = kernel(K, rref_mod_2) X = np.array(basisKerK).transpose() _, _, kerK = kernel(K, rref_mod_2) - assert len(kerK) == 1 + assert len(kerK) == 1, len(kerK) h = kerK[0] zero_tag = gf128_to_vec(bytes_to_gf128(gmac(vec_to_gf128(h), 0, aad, orig_ct)))[:mac_bytes*8] @@ -774,24 +776,25 @@ def forbidden_attack_demo(): assert succeeded def nonce_truncation_demo(): - # Should work with non-block size multiples. + # Doesn't work with non-block size multiples. # Need to modify to consider padding, but we can't mess with the bits in the padding, # nor can we extend ad/ct unless we also change length block. - k = b'YELLOGIOJEWARINE' - aad = b'YELLOW_SUBMAFINERELLOWPUBMARINF_' - MACBYTES=1 - pt = b'CELERYPATCHWORKS'*(2**5) - nonce = b'JORGELBORGES' - ct, mac = gcm_encrypt(k, nonce, aad, pt) - # ct, mac = gcm_encrypt(k, nonce, aad, pt, mac_bytes=MACBYTES) - mac = mac[:1] + k = b'tlonorbistertius' + aad = b'yellow_submarine' + mac_bytes=2 + pt = b'celerypatchworks'*(2**9) + nonce = b'jorgelborges' + ct, mac = gcm_encrypt(k, nonce, aad, pt, mac_bytes=mac_bytes) def oracle(base, aad, mac, nonce): - cipher = AES.new(k, mode=AES.MODE_GCM, nonce=nonce, mac_len=MACBYTES) - cipher.update(aad) - pt = cipher.decrypt_and_verify(base, mac) - h, s = nonce_truncation_recover_secrets(ct, mac, nonce, MACBYTES, aad, oracle, compute_T_once=True) + decryptor = Cipher( + algorithms.AES(k), + modes.GCM(nonce, mac, min_tag_length=mac_bytes), + ).decryptor() + decryptor.authenticate_additional_data(aad) + decryptor.update(base) + decryptor.finalize() + + h, s = nonce_truncation_recover_secrets(ct, mac, nonce, mac_bytes, aad, oracle, compute_T_once=mac_bytes==1) assert h == authentication_key(k) - return h, s if __name__ == "__main__": nonce_truncation_demo() -- cgit v1.2.3