def ShiftRow(cost=False): """ TEST: >>> Tests.ShiftRow() Testing ShiftRow """ print("%s ShiftRow" % ("Costing" if cost else "Testing")) from QTests.AES import ShiftRow # pylint: disable=no-name-in-module,import-error def bits_to_int(bits): return sum([1 << i if bits[i] == 1 else 0 for i in range(8)]) state = { 'Nb': 4, 'a': [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]] } qstate = [[GF256Element(state['a'][j][i]).coeffs for i in range(4)] for j in range(4)] qstate = [[e for sub in qstate[j] for e in sub] for j in range(4)] qstate = [i for e in qstate for i in e] if cost: return ShiftRow.estimate_resources(_state=qstate, costing=True) aes.ShiftRow(state) qstate = ShiftRow.toffoli_simulate(_state=qstate, costing=False) qstate = [[ bits_to_int(qstate[j][i * 8:(i + 1) * 8]) for i in range(4) ] for j in range(4)] assert (state['a'] == qstate)
def AddRoundKey(cost=False): """ TEST: >>> Tests.AddRoundKey() Testing AddRoundKey """ print("%s AddRoundKey" % ("Costing" if cost else "Testing")) from random import randint from QTests.AES import AddRoundKey # pylint: disable=no-name-in-module,import-error def bits_to_int(bits): return sum([1 << i if bits[i] == 1 else 0 for i in range(8)]) trials = 128 res = [] for t in range(trials): state = { 'Nb': 4, 'a': [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]] } key = [[randint(0, 255) for i in range(4)] for j in range(4)] qstate = [[ GF256Element(state['a'][j][i]).coeffs for i in range(4) ] for j in range(4)] qstate = [[e for sub in qstate[j] for e in sub] for j in range(4)] qstate = [i for e in qstate for i in e] qkey = [[GF256Element(key[j][i]).coeffs for i in range(4)] for j in range(4)] qkey = [[e for sub in qkey[j] for e in sub] for j in range(4)] qkey = [i for e in qkey for i in e] if cost: return AddRoundKey.estimate_resources(_state=qstate, _round_key=qkey) aes.AddRoundKey(state, key) qstate = AddRoundKey.toffoli_simulate(_state=qstate, _round_key=qkey) qstate = [[ bits_to_int(qstate[j][i * 8:(i + 1) * 8]) for i in range(4) ] for j in range(4)] res.append(state['a'] == qstate) assert (res == [True] * trials)
def MixColumn(in_place=True, cost=False): """ TEST: >>> Tests.MixColumn(in_place=True) Testing MixColumn(in_place=True) >>> Tests.MixColumn(in_place=False) Testing MixColumn(in_place=False) """ from random import randint print("%s MixColumn(in_place=%s)" % ("Costing" if cost else "Testing", in_place)) from QTests.AES import MixColumn # pylint: disable=no-name-in-module,import-error trials = 128 res = [] for _ in range(trials): state = { 'Nb': 4, 'a': [[randint(0, 255) for _ in range(4)] for __ in range(4)] } # state = {'Nb': 4, 'a': [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]} qstate = [[ GF256Element(state['a'][j][i]).coeffs for i in range(4) ] for j in range(4)] qstate = [[e for sub in qstate[j] for e in sub] for j in range(4)] qstate = [i for e in qstate for i in e] if cost: return MixColumn.estimate_resources(_state=qstate, in_place=in_place, costing=True) def bits_to_int(bits): return sum([1 << i if bits[i] == 1 else 0 for i in range(8)]) # Mixcols using GF256 library aes.MixColumn(state) # Mixcols using Q# qstate = MixColumn.toffoli_simulate(_state=qstate, in_place=in_place, costing=False) qstate = [[ bits_to_int(qstate[j][i * 8:(i + 1) * 8]) for i in range(4) ] for j in range(4)] res.append(state['a'] == qstate) if state['a'] != qstate: print(" state: ", state['a']) print("qstate: ", qstate) assert (res == [True] * trials)
def Sixteenth(cost=False): """ TESTS: >>> Tests.Sixteenth() Testing Sixteenth """ print("%s Sixteenth" % ("Costing" if cost else "Testing")) from QTests.GF256 import Sixteenth # pylint: disable=no-name-in-module,import-error res = [] for _x in range(256): x = GF256Element(_x) if cost: return Sixteenth.estimate_resources(_a=x.coeffs, costing=True) x16 = x**16 _x16 = GF256Element( Sixteenth.toffoli_simulate(_a=x.coeffs, costing=False)) res.append(x16 == _x16) if (x16 != _x16): print("Error") print(" x:", x) print(" x16:", x16) print("qx16:", _x16)
def Inverse(cost=False): """ TESTS: >>> Tests.Inverse() Testing Inverse """ print("%s Inverse" % ("Costing" if cost else "Testing")) from QTests.GF256 import Inverse # pylint: disable=no-name-in-module,import-error res = [] for _x in range(256): x = GF256Element(_x) if cost: return Inverse.estimate_resources(_a=x.coeffs, costing=True) x16 = x.inverse() _x16 = GF256Element( Inverse.toffoli_simulate(_a=x.coeffs, costing=False)) res.append(x16 == _x16) if (x16 != _x16): print("Error") print(" x:", x) print(" x16:", x16) print("qx16:", _x16) pass
def KeyExpansion(key, Nr, debug=False): Nb = key['Nb'] Nk = key['Nk'] W = [[0] * 4 for _ in range(Nb * (Nr + 1))] x = GF256Element(2) for i in range(Nk): W[i] = key['k'][i] for i in range(Nk, Nb * (Nr + 1)): temp = W[i - 1] if i % Nk == 0: temp = SubByte(RotByte(temp)) if debug: # print(i//Nk, (i//Nk - 1) % 255, hex(int(x ** ((i//Nk - 1) % 255)))) pass temp[0] ^= int(x**((i // Nk - 1) % 255)) elif i % Nk == 4 and Nk > 6: temp = SubByte(temp) W[i] = [W[i - Nk][j] ^ temp[j] for j in range(4)] return [W[i:i + Nb] for i in range(0, Nb * (Nr + 1), Nb)]
def GroverOracle(smart_wide=True, Nr=10, Nk=4, pairs=1, in_place_mixcolumn=False, cost=False): """ TEST: >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=10, Nk=4, pairs=1) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=10, Nk=4, pairs=1) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=10, Nk=4, pairs=2) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=10, Nk=4, pairs=2) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=12, Nk=6, pairs=1) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=12, Nk=6, pairs=1) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=12, Nk=6, pairs=2) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=12, Nk=6, pairs=2) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8, pairs=1) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8, pairs=1) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8, pairs=2) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8, pairs=2) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=10, Nk=4, pairs=1) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=10, Nk=4, pairs=1) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=10, Nk=4, pairs=2) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=10, Nk=4, pairs=2) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=12, Nk=6, pairs=1) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=12, Nk=6, pairs=1) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=12, Nk=6, pairs=2) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=12, Nk=6, pairs=2) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8, pairs=1) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8, pairs=1) >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8, pairs=2) Testing GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8, pairs=2) # >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8, pairs=3) # Testing GroverOracle(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8, pairs=3) # >>> Tests.GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8, pairs=3) # Testing GroverOracle(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8, pairs=3) """ print( "%s GroverOracle(smart_wide=%s, in_place_mixcolumn=%s, Nr=%d, Nk=%d, pairs=%d)" % ("Costing" if cost else "Testing", smart_wide, in_place_mixcolumn, Nr, Nk, pairs)) from random import randint if smart_wide: from QTests.AES import SmartWideGroverOracle as GroverOracle # pylint: disable=no-name-in-module,import-error def bits_to_int(bits): return sum([1 << i if bits[i] == 1 else 0 for i in range(8)]) trials = 10 res = [] for t in range(trials): message = { 'Nb': 4, 'a': [[randint(0, 255) for i in range(4)] for j in range(4 * pairs)] } qmessage = [[ GF256Element(message['a'][j][i]).coeffs for i in range(4) ] for j in range(4 * pairs)] qmessage = [[e for sub in qmessage[j] for e in sub] for j in range(4 * pairs)] qmessage = [i for e in qmessage for i in e] key = { 'Nb': 4, 'Nk': Nk, 'k': [[randint(0, 255) for i in range(4)] for j in range(Nk)] } qkey = [[GF256Element(key['k'][j][i]).coeffs for i in range(4)] for j in range(Nk)] qkey = [[e for sub in qkey[j] for e in sub] for j in range(Nk)] qkey = [i for e in qkey for i in e] # compute p-c pairs ciphertexts = [] for _ in range(pairs): ciphertext = {'Nb': 4, 'a': message['a'][_ * 4:(_ + 1) * 4]} aes.InnerRijndael(key, ciphertext, Nb=4, Nk=Nk, Nr=Nr) ciphertexts.append(ciphertext) target_ciphertext = [[ GF256Element(c['a'][j][i]).coeffs for i in range(4) ] for c in ciphertexts for j in range(4)] target_ciphertext = [[ e for sub in target_ciphertext[j] for e in sub ] for j in range(4 * pairs)] target_ciphertext = [i for e in target_ciphertext for i in e] # test also that we correctly fail to identify wrong keys flip = bool(randint(0, 1)) if flip: qkey[0] = 0 if qkey[0] == 1 else 1 qgrover = GroverOracle.toffoli_simulate( _key=qkey, _plaintexts=qmessage, target_ciphertext=target_ciphertext, pairs=pairs, Nr=Nr, Nk=Nk, in_place_mixcolumn=in_place_mixcolumn, costing=False) res.append(qgrover == int(not flip)) assert (res == [True] * trials)
def Rijndael(smart_wide=True, Nr=10, Nk=4, in_place_mixcolumn=False, cost=False): """ TEST: >>> Tests.Rijndael(smart_wide=True, in_place_mixcolumn=False, Nr=10, Nk=4) Testing Rijndael(smart_wide=True, in_place_mixcolumn=False, Nr=10, Nk=4) >>> Tests.Rijndael(smart_wide=True, in_place_mixcolumn=False, Nr=12, Nk=6) Testing Rijndael(smart_wide=True, in_place_mixcolumn=False, Nr=12, Nk=6) >>> Tests.Rijndael(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8) Testing Rijndael(smart_wide=True, in_place_mixcolumn=False, Nr=14, Nk=8) >>> Tests.Rijndael(smart_wide=True, in_place_mixcolumn=True, Nr=10, Nk=4) Testing Rijndael(smart_wide=True, in_place_mixcolumn=True, Nr=10, Nk=4) >>> Tests.Rijndael(smart_wide=True, in_place_mixcolumn=True, Nr=12, Nk=6) Testing Rijndael(smart_wide=True, in_place_mixcolumn=True, Nr=12, Nk=6) >>> Tests.Rijndael(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8) Testing Rijndael(smart_wide=True, in_place_mixcolumn=True, Nr=14, Nk=8) >>> Tests.Rijndael(smart_wide=False, in_place_mixcolumn=True, Nr=10, Nk=4) Testing Rijndael(smart_wide=False, in_place_mixcolumn=True, Nr=10, Nk=4) >>> Tests.Rijndael(smart_wide=False, in_place_mixcolumn=True, Nr=12, Nk=6) Testing Rijndael(smart_wide=False, in_place_mixcolumn=True, Nr=12, Nk=6) >>> Tests.Rijndael(smart_wide=False, in_place_mixcolumn=True, Nr=14, Nk=8) Testing Rijndael(smart_wide=False, in_place_mixcolumn=True, Nr=14, Nk=8) """ print( "%s Rijndael(smart_wide=%s, in_place_mixcolumn=%s, Nr=%d, Nk=%d)" % ("Costing" if cost else "Testing", smart_wide, in_place_mixcolumn, Nr, Nk)) from random import randint if smart_wide: from QTests.AES import SmartWideRijndael as Rijndael # pylint: disable=no-name-in-module,import-error else: from QTests.AES import WideRijndael as Rijndael # pylint: disable=no-name-in-module,import-error def bits_to_int(bits): return sum([1 << i if bits[i] == 1 else 0 for i in range(8)]) trials = 4 res = [] for t in range(trials): message = { 'Nb': 4, 'a': [[randint(0, 255) for i in range(4)] for j in range(4)] } key = { 'Nb': 4, 'Nk': Nk, 'k': [[randint(0, 255) for i in range(4)] for j in range(Nk)] } qmessage = [[ GF256Element(message['a'][j][i]).coeffs for i in range(4) ] for j in range(4)] qmessage = [[e for sub in qmessage[j] for e in sub] for j in range(4)] qmessage = [i for e in qmessage for i in e] qkey = [[GF256Element(key['k'][j][i]).coeffs for i in range(4)] for j in range(Nk)] qkey = [[e for sub in qkey[j] for e in sub] for j in range(Nk)] qkey = [i for e in qkey for i in e] if cost: return Rijndael.estimate_resources( _message=qmessage, _key=qkey, Nr=Nr, Nk=Nk, in_place_mixcolumn=in_place_mixcolumn, costing=True) # qstate = [e for sub in qstate for e in sub] aes.InnerRijndael(key, message, Nb=4, Nk=Nk, Nr=Nr) qmessage = Rijndael.toffoli_simulate( _message=qmessage, _key=qkey, Nr=Nr, Nk=Nk, in_place_mixcolumn=in_place_mixcolumn, costing=False) qmessage = [[ bits_to_int(qmessage[j][i * 8:(i + 1) * 8]) for i in range(4) ] for j in range(4)] if message['a'] != qmessage: print('c', message['a']) print('q', qmessage) print() res.append(message['a'] == qmessage) assert (res == [True] * trials)
def KeyExpansion(in_place=False, cost=False, Nr=10, Nk=4): """ TEST: >>> Tests.KeyExpansion(in_place=True, Nr=10, Nk=4) Testing KeyExpansion(in_place=True, Nr=10, Nk=4) >>> Tests.KeyExpansion(in_place=True, Nr=12, Nk=6) Testing KeyExpansion(in_place=True, Nr=12, Nk=6) >>> Tests.KeyExpansion(in_place=True, Nr=14, Nk=8) Testing KeyExpansion(in_place=True, Nr=14, Nk=8) >>> Tests.KeyExpansion(in_place=False, Nr=10, Nk=4) Testing KeyExpansion(in_place=False, Nr=10, Nk=4) >>> Tests.KeyExpansion(in_place=False, Nr=12, Nk=6) Testing KeyExpansion(in_place=False, Nr=12, Nk=6) >>> Tests.KeyExpansion(in_place=False, Nr=14, Nk=8) Testing KeyExpansion(in_place=False, Nr=14, Nk=8) """ print("%s KeyExpansion(in_place=%s, Nr=%d, Nk=%d)" % ("Costing" if cost else "Testing", in_place, Nr, Nk)) from random import randint if in_place: from QTests.AES import InPlaceKeyExpansion as KeyExpansion # pylint: disable=no-name-in-module,import-error else: from QTests.AES import KeyExpansion # pylint: disable=no-name-in-module,import-error def bits_to_int(bits): return sum([1 << i if bits[i] == 1 else 0 for i in range(8)]) trials = 1 res = [] for t in range(trials): key = { 'Nb': 4, 'Nk': Nk, 'k': [[randint(0, 255) for i in range(4)] for j in range(Nk)] } qkey = [ GF256Element(key['k'][j][i]).coeffs for j in range(Nk) for i in range(4) ] qkey = [e for sub in qkey for e in sub] if cost: return KeyExpansion.estimate_resources(_key=qkey, Nr=Nr, Nk=Nk, costing=True) key = aes.KeyExpansion(key, Nr) qkey = KeyExpansion.toffoli_simulate(_key=qkey, Nr=Nr, Nk=Nk, costing=False) qkey = [ bits_to_int(qkey[i * 8:(i + 1) * 8]) for i in range(len(qkey) // 8) ] qkey = [qkey[i * 4:(i + 1) * 4] for i in range(len(qkey) // 4)] qkey = [qkey[i * 4:(i + 1) * 4] for i in range(len(qkey) // 4)] if key != qkey: print('c', key) print('q', qkey) res.append(key == qkey) assert (res == [True] * trials)