def test_mult(): key_cipher = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) v1 = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) v2 = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) sub = Master.get_one_sub(key_cipher) shares1 = Master.get_shares(v1, sub) shares2 = Master.get_shares(v2, sub) sub.initShares(shares1) for s, mini in enumerate(sub.minicircuits): mini.state2 = shares2[s] sub.multiply(inputs1=[mini.state2 for mini in sub.minicircuits]) reconstruct = Master.reconstructShares(sub) if not np.array_equal(v1 * v2, reconstruct): return 0 else: return 1
def get_one_sub(key_cipher): key1 = np.array([[GF2int(randint(0,255)) for i in range(4)] for j in range(4)], dtype=GF2int) key2 = np.array([[GF2int(randint(0,255)) for i in range(4)] for j in range(4)], dtype=GF2int) key3 = np.array([[GF2int(randint(0,255)) for i in range(4)] for j in range(4)], dtype=GF2int) key1 = "".join(format(y, '02x') for x in key1 for y in x) key2 = "".join(format(y, '02x') for x in key2 for y in x) key3 = "".join(format(y, '02x') for x in key3 for y in x) return SubCircuit([key1,key2,key3],key_cipher)
def corrRandom(self): """Return random correlated value array""" cnt = self.ctr.__call__() cipher1 = AES.new(self.key1) cipher2 = AES.new(self.key2) ct1 = cipher1.encrypt(cnt).encode("hex") ct2 = cipher2.encrypt(cnt).encode("hex") randomness = np.zeros([4,4],dtype=GF2int) for i in range(0,4): for j in range(0,4): randomness[i,j] = GF2int(int(ct2[(i*4+j)*2:(i*4+j)*2+2],16)) + GF2int(int(ct1[(i*4+j)*2:(i*4+j)*2+2],16)) return randomness
def test_AES(): # INIT KEYS AND PLAINTEXT key1 = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) key2 = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) key3 = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) key1 = "".join(format(y, '02x') for x in key1 for y in x) key2 = "".join(format(y, '02x') for x in key2 for y in x) key3 = "".join(format(y, '02x') for x in key3 for y in x) key_cipher = np.array([[GF2int(0) for i in range(4)] for j in range(4)], dtype=GF2int) plain_text = np.array([[GF2int(0) for i in range(4)] for j in range(4)], dtype=GF2int) plain_text_str = "".join(format(y, '02x') for x in plain_text for y in x) key_cipher_str = "".join(format(y, '02x') for x in key_cipher for y in x) aes_ref = AES.new(key_cipher_str) cipher_ref_str = aes_ref.encrypt(plain_text_str).encode("hex") W = aes.ExpandRoundKey(key_cipher) master = Master(key_cipher, 4) keys = [key1, key2, key3] sub = SubCircuit( np.array([ MiniCircuit(keys[s % 3], keys[(s + 1) % 3], W) for s in range(3) ])) randomness = sub.getCorrRandom() shares = [Secret(), Secret(), Secret()] for s in range(0, 3): shares[s].alpha = randomness[s] shares[s].x = plain_text + randomness[(s - 1) % 3] W = aes.ExpandRoundKey(key_cipher) sub.initShares(shares) sub.AES() shared = master.reconstructShares(sub) state = aes.AES(key_cipher, plain_text) if (not np.array_equal(state, shared)): return 0 else: return 1
def __init__(self,key_cipher, subcircuits=[], lamb=1,createSub=False,flags=[]): self.key_cipher = key_cipher self.subcircuits = subcircuits self.flags = np.array(flags) if createSub: for i in range(0,lamb): key1 = np.array([[GF2int(randint(0,255)) for i in range(4)] for j in range(4)], dtype=GF2int) key2 = np.array([[GF2int(randint(0,255)) for i in range(4)] for j in range(4)], dtype=GF2int) key3 = np.array([[GF2int(randint(0,255)) for i in range(4)] for j in range(4)], dtype=GF2int) key1 = "".join(format(y, '02x') for x in key1 for y in x) key2 = "".join(format(y, '02x') for x in key2 for y in x) key3 = "".join(format(y, '02x') for x in key3 for y in x) self.subcircuits.append(SubCircuit([key1,key2,key3],key_cipher))
def test_addKey(): key_cipher = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) v = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) sub = Master.get_one_sub(key_cipher) shares = Master.get_shares(v, sub) sub.initShares(shares) sub.addKey(0) reconstruct = Master.reconstructShares(sub) if not np.array_equal(v + key_cipher, reconstruct): return 0 else: return 1
def test_Sbox(): key_cipher = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) v = np.array([[GF2int(randint(0, 255)) for i in range(4)] for j in range(4)], dtype=GF2int) sub = Master.get_one_sub(key_cipher) shares = Master.get_shares(v, sub) sub.initShares(shares) sub.SubBytes() reconstruct = Master.reconstructShares(sub) if not np.array_equal(np.array(sbox[np.array(v, dtype=int)], dtype=GF2int), reconstruct): return 0 else: return 1
def test_div_scalar2(self): """Test that dividing by a scalar is the same as multiplying by the scalar's inverse""" a = Polynomial(map(GF2int, [5,3,1,1,6,8])) scalar = GF2int(50) self.assertEqual( a * Polynomial(x0=scalar), a // Polynomial(x0=scalar.inverse()) )
def test_div_scalar(self): """Tests division by a scalar""" numbers = map(GF2int, [5,20,50,100,134,158,0,148,233,254,4,5,2]) scalar = GF2int(17) poly = Polynomial(numbers) scalarpoly = Polynomial(x0=scalar) self.assertEqual( list((poly // scalarpoly).coefficients), map(lambda x: x / scalar, numbers) )
def ExpandRoundKey(key): Nk = 4 Nb = 16 Nr = 10 W = np.zeros([4, (Nr + 1) * 4], dtype=GF2int) W.fill(GF2int(1)) W[:4, 0:4] = key for i in range(4, (Nr + 1) * 4): temp = np.array(W[:, i - 1]) if i % Nk == 0: temp_v = temp[0] temp[0:3] = temp[1:4] temp[3] = temp_v temp = SubBytes(temp) temp[0] = temp[0] + Rcon(GF2int(i / Nk)) W[:, i] = np.array(W[:, i - Nk] + temp) return W
def test_arithmetic(self): a = GF2int(3) b = GF2int(9) self.assertEqual(a + b, 10) self.assertEqual(b + a, 10) self.assertEqual(3 + b, 10) self.assertEqual(a + 9, 10) self.assertEqual(a - b, 10) self.assertEqual(b - a, 10) self.assertEqual(3 - b, 10) self.assertEqual(a - 9, 10) self.assertEqual(a * b, 27) self.assertEqual(b * a, 27) self.assertEqual(3 * b, 27) self.assertEqual(a * 9, 27) self.assertEqual(b * b.inverse(), 1) self.assertEqual(b / b, 1) self.assertEqual(b / a, 7) self.assertEqual(9 / a, 7) self.assertEqual(b / 3, 7) self.assertRaises(Exception, lambda: b**a) self.assertEqual(b**3, 127) self.assertRaises(Exception, lambda: a**b) self.assertEqual(a**9, 46) self.assertEqual(a**5, 51) self.assertEqual( a**1000, 148 ) # big overflow to see if it correctly does a modular reduction self.assertEqual(b.inverse(), 79) self.assertEqual(b * 79, 1)
def test_multiply_nolut(self): '''Try to multiply without look-up tables (necessary to build the look-up tables!)''' a = GF2int(3) b = GF2int(9) self.assertEqual(a * b, a.multiply(b)) # More Galois Field multiplications self.assertEqual( GF2int(5).multiply(GF2int(6), prim=0x11b, field_charac_full=256), 30) self.assertEqual( GF2int(3).multiply(GF2int(125), prim=0x11b, field_charac_full=256), 135) self.assertEqual( GF2int(2).multiply(GF2int(200), prim=0x11d, field_charac_full=256), 141) self.assertEqual(GF2int(2).multiply_slow(200, prim=0x11d), 141) # Multiplications in GF(2^7) self.assertEqual( GF2int(3).multiply(GF2int(125), prim=0xfd, field_charac_full=128), 122) # Multiplications outside of the finite field (we revert to standard integer multiplications just to see if it works) self.assertEqual(GF2int(3).multiply(125, prim=0), 375) self.assertEqual( GF2int(4).multiply_slow(125, prim=0), 500) # the second method, just to check that everything's alright
def test_fermats_theorem(self): for x in range(1, 256): self.assertEqual(GF2int(x)**255, 1)
def Rcon(i): b = GF2int(1) for g in range(1, i): b = b * GF2int(2) return b
def __init__(self): self.alpha = np.array([[GF2int(0) for i in range(4)] for j in range(4)], dtype=GF2int) self.x = np.array([[GF2int(0) for i in range(4)] for j in range(4)], dtype=GF2int)
def mix_one_col(col): m = np.array( [[GF2int(2), GF2int(3), GF2int(1), GF2int(1)], [GF2int(1), GF2int(2), GF2int(3), GF2int(1)], [GF2int(1), GF2int(1), GF2int(2), GF2int(3)], [GF2int(3), GF2int(1), GF2int(1), GF2int(2)]], dtype=GF2int) return np.dot(m, col)
def GF_from_bits(b): t = 0 for i, val in enumerate(b): t += val * (2**i) return GF2int(t)
def inverse_or_zero(i): if i == GF2int(0): return i else: return i.inverse()