def QR_chacha(X: tuple) -> tuple: """ChaCha QR function.""" a, b, c, d = X a = Binary(a) b = Binary(b) c = Binary(c) d = Binary(d) # 1 a = a % b d = d ^ a d = d // 16 # 2 c = c % d b = b ^ c b = b // 12 # 3 a = a % b d = d ^ a d = d // 8 # 4 c = c % d b = b ^ c b = b // 7 return (a.bits, b.bits, c.bits, d.bits)
def random_bits(X): Y = list(X) for i in range(len(X)): tmp_bin = Binary() tmp_bin.gen_random(word_size=len(X[i])) Y[i] = tmp_bin return tuple(Y)
def __init__(self, test_mode:bool=False): self.test_mode = test_mode self.a_vects = [] self.b_vects = [] for i in range(4): a_n = '' b_n = '' for j in range(4): a_n += Binary(PRG.A_VECTOR[i][j]).get_bin(8) b_n += Binary(PRG.B_VECTOR[i][j]).get_bin(8) #A_bin_n = A_vec_n.get_bin(8) #B_bin_n = B_vec_n.get_bin(8) #a_n += A_vec_n #b_n += B_vec_n #a_n += self.to_binary(PRG.A_VECTOR[i][j]) #b_n += self.to_binary(PRG.B_VECTOR[i][j]) self.a_vects.append(a_n) self.b_vects.append(b_n) # Log self.single_xor = 0 self.XORs = 0 self.mod_adds = 0 self.shifts = 0 self.shift_length = 0 self.QRs = 0 self.total_runs = 0 self.QR_x = [] self.QR_y = [] self.DRF_in = []
def generate_incr_space(word_size:int): """Return a list of all word_size bit binary numbers.""" space = [] for i in range(2**word_size): a = Binary(i) % word_size a = a.split_string() space.append(a) return space
def get_ints(X:list): """Convert list of ints from list of bytes.""" X_ints = [] for value in X: X_bin = Binary().combine_string(value) X_ints.append(X_bin.get_dec()) return X_ints
def HW(word: Binary) -> int: """Returns the hamming weight of input word.""" if type(word) is tuple: word = Binary().combine_string(word) if type(word) is Binary: word = word.bits weight = word.count('1') return weight
def get_freq_dist(lst:list, word_size:int): freqs = [0] * 2**word_size ints = [] for i in range(len(lst)): X_bin = Binary().combine_string(lst[i]) X_int = X_bin.get_dec() freqs[X_int] += 1 ints.append(X_int) return freqs, ints
def test_get_hex(): a = Binary(3) b = Binary(10) c = Binary(8) assert a.get_hex() == '3' assert b.get_hex() == 'a' assert c.get_hex() == '8'
def test_get_dec(): a = Binary(3) b = Binary(10) c = Binary(8) assert a.get_dec() == 3 assert b.get_dec() == 10 assert c.get_dec() == 8
def HD(word_1: Binary, word_2: Binary) -> int: """Returns the hamming distance between two input words.""" if type(word_1) is tuple: word_1 = Binary().combine_string(word_1) if type(word_2) is tuple: word_2 = Binary().combine_string(word_2) distance = 0 for i in range(len(word_1)): if word_1[i] != word_2[i]: distance += 1 return distance
def hash_function(self, words:tuple) -> str: """The hash function does the following: 1. Split the 64 byte input into 16 words. 2. For all words: Update by littleendian function. 3. Run all words through doubleround^10. 4. Do the last magic. (See link.)""" # 1. Split words. #words = [] #for i in range(16): # word = '' # for j in range(4): # word += input_bytes[j + i*4] # words.append(word) # 2. Run through littleendian function. for word in words: word = self.littleendian_function(word) """ # 2.5 merge words --> x_list. x_list = '' for word in words: x_list += word """ # 3. Run all words though doubleround x10. x_list = words + tuple() # The cool way to do copy for tuples. for i in range(10): assert len(x_list) == 16 x_list = self.doubleround_function(x_list) assert len(x_list) == 16 # 4. The final magic output_list = [] for i in range(16): input_1 = Binary(x_list[i]) input_2 = Binary(words[i]) output_element = input_1 % input_2 output_element = output_element.bits #output_element = self.sum_words(x_list[i], words[i]) output_element = self.littleendian_function(output_element) output_list.append(output_element) output = '' for output_element in output_list: output += output_element return output
def HD_2(word_1: Binary, word_2: Binary) -> int: """Alternative (and slower) version of HD.""" if type(word_1) is tuple: word_1 = Binary().combine_string(word_1) if type(word_2) is tuple: word_2 = Binary().combine_string(word_2) if type(word_1) is str: word_1 = Binary(word_1) if type(word_2) is str: word_2 = Binary(word_2) xor = word_1 ^ word_2 distance = HW(xor) return distance
def get_plaintext(number): binary = Binary(number) # Random chars: #string = gen_random_string(length=128) # Random binary values: #binary.gen_random(word_size=128) #string = binary.bits # Counting values: string = binary.get_bin(word_size=128) return string
def test_init(): Bin1 = Binary() assert type(Bin1) is Binary assert type(Bin1.bits) is str assert Bin1.bits == '0' Bin2 = Binary(5) assert type(Bin2) is Binary assert type(Bin2.bits) is str assert Bin2.bits == '101' Bin3 = Binary('1100') assert type(Bin3) is Binary assert type(Bin3.bits) is str assert Bin3.bits == '1100'
def test_incement(): a = Binary(30) assert a.get_dec() == 30 assert a.bits == '11110' a.incr() assert a.get_dec() == 31 assert a.bits == '11111' a.incr(4) assert a.get_dec() == 35 assert a.bits == '100011'
def test_decrement(): a = Binary(30) assert a.get_dec() == 30 assert a.bits == '11110' a.decr() assert a.get_dec() == 29 assert a.bits == '11101' a.decr(4) assert a.get_dec() == 25 assert a.bits == '11001'
def test_gen_random(): Bin = Binary() assert Bin.bits == '0' Bin.gen_random(32) assert type(Bin.bits) is str assert len(Bin.bits) == 32 zeros = 0 ones = 0 for bit in Bin.bits: if bit == '0': zeros += 1 else: ones += 1 assert 4 < zeros < 28 assert 4 < ones < 28
def test_set_at(): a = Binary('10101') assert a.bits == '10101' a.set_at(2, '0') assert a.bits == '10001' a.set_at(1, '1') assert a.bits == '11001' a.set_at(0, '1') assert a.bits == '11001'
def test_flip_bit_at(): a = Binary('10101') assert a.bits == '10101' a.flip_bit_at(2) assert a.bits == '10001' a.flip_bit_at(1) assert a.bits == '11001' a.flip_bit_at(0) assert a.bits == '01001'
def gen_random_bits(word_size): """Return a random set of bits, of length word_size, as a Binary object.""" bits = '' for i in range(word_size): bits += random.choice(('0', '1')) return Binary(bits)
def test_random_index(): a = Binary('1001101010') indexes = [0] * len(a) runs = 100 for i in range(runs): index = random.randint(0, len(a.bits) - 1) indexes[index] += 1 for index in indexes: assert index > 0
def test_set_bin(): Bin = Binary() Bin.set_bin(3) assert Bin == '11' Bin.set_bin(10) assert Bin == '1010' Bin.set_bin(8) assert Bin == '1000'
def test_is_binary(): Bin = Binary() assert Bin.is_binary('10101') assert Bin.is_binary('0') assert not Bin.is_binary('102') assert not Bin.is_binary('1af0') assert not Bin.is_binary(10)
def random_flips(function=QR, word_size:int=12): X = Binary()#'0000000000000000') X.gen_random(word_size) X = X.split_string() Y = function(X) HD_lists = [] for i in range(100): Xs = generate_random_flipped_space(X, runs=100) #Ys = QR_on_list(Xs) Ys = [] for X_i in Xs: Ys.append(function(X_i)) Y_base = [Y] * len(Ys) HDs = HDs_of_lists(Y_base, Ys) HD_lists.append(HDs) return HD_lists
def HW_2(word: Binary) -> int: """Alternative (and slower) version of HW.""" if type(word) is tuple: word = Binary().combine_string(word) if type(word) is Binary: word = word.bits weight = 0 for bit in word: if bit == '1': weight += 1 return weight
def test_add(): a = Binary(123) b = Binary(345) c = Binary(468) assert a + b == c assert a.is_binary(a) assert a.is_binary(a + b)
def test_while_bits(): a = '0100101' b = Binary('01010111') c = ('010', '101', '110', '100') d = [Binary('1010'), Binary('001'), '100010101010'] A = whipe_bits(a) B = whipe_bits(b, default='1') C = whipe_bits(c) D = whipe_bits(d) assert type(A) is str assert len(A) == len(a) assert A == '0000000' assert type(B) is Binary assert len(B) == len(b) assert B == Binary('11111111') assert type(C) is tuple assert len(C) == len(c) assert C == ('000', '000', '000', '000') assert type(C[0]) == type(C[1]) == type(C[2]) == type(C[3]) == str assert type(d) is list assert len(D) == len(d) assert D == [Binary('0000'), Binary('000'), '000000000000'] assert type(D[0]) == type(D[1]) == Binary assert type(D[2]) == str
def xor_0(X, bit='0'): X = list(X) for i in range(len(X)): new_word = '' for j in range(len(X[i])): if X[i][j] == bit: new_word += '0' else: new_word += '1' X[i] = Binary(new_word) return tuple(X)
def incremental_space(function=QR, word_size:int = 12): X = Binary()#'0000000000000000') X.gen_random(word_size) X = X.split_string() Y = function(X) Xs = generate_incr_space(word_size) #Ys = QR_on_list(Xs) Ys = [] for X in Xs: Ys.append(function(X)) Y_base = [Y] * len(Ys) HDs = HDs_of_lists(Y_base, Ys) multi_line_chart( lines=[HDs], title='HDs of incremental outputs', x_label='bits', y_label='Hamming distance and weight' )
def QR(X: tuple) -> tuple: """Salsa QR function.""" #print('X:', X) x0, x1, x2, x3 = X word_size = len(x0) x0 = Binary(x0) x1 = Binary(x1) x2 = Binary(x2) x3 = Binary(x3) y1 = x1 ^ ((x0 % x3) // 7) y2 = x2 ^ ((y1 % x0) // 9) y3 = x3 ^ ((y2 % y1) // 13) y0 = x0 ^ ((y3 % y2) // 18) y0_ = y0.get_bin(word_size) y1_ = y1.get_bin(word_size) y2_ = y2.get_bin(word_size) y3_ = y3.get_bin(word_size) Y = (y0_, y1_, y2_, y3_) return Y