def find_r4(start_value, steps, k1, k2, f1, f2): """ Iterates through all posible values for r4 and performs the attack :param start_value: start value for r4 :param steps: number of iterations for r4 :param k1, k2: keystream 1 and 2 :param f: frame counter for k1 """ for i in range(start_value, start_value + steps, 1): if solution_found.is_set(): break r4 = LFSR(R4_SIZE, R4_CLOCK_BITS, R4_TAPS, [], None, None, i) if r4.get_bit(10) == 1: perform_attack(r4, k1, k2, f1, f2)
def genGeffe(coef1, s1, coef2, s2, coef3, s3, length): c1 = LFSR(coef1, s1, length) c2 = LFSR(coef2, s2, length) c3 = LFSR(coef3, s3, length) res = [] for i, j, k in zip(c1, c2, c3): x1 = i * j x2 = j * k x3 = k f = x1 ^ x2 ^ x3 res.append(f) return res
def convert_solution_to_lfsrs(solution): """ Converts the values from the Gauss algorithm to LFSR objects. :param solution: array with the values from the gauss algorithm :return register 1, 2 and 3 as LFSR object """ r1_value = solution[R1_START_IN_SOLUTION:R1_END_IN_SOLUTION] r2_value = solution[R2_START_IN_SOLUTION:R2_END_IN_SOLUTION] r3_value = solution[R3_START_IN_SOLUTION:R3_END_IN_SOLUTION] r1 = LFSR(R1_SIZE, [], R1_TAPS, R1_MAJORITY_BITS, R1_NEGATED_BIT) r2 = LFSR(R2_SIZE, [], R2_TAPS, R2_MAJORITY_BITS, R2_NEGATED_BIT) r3 = LFSR(R3_SIZE, [], R3_TAPS, R3_MAJORITY_BITS, R3_NEGATED_BIT) r1.register = BitVector(bitlist=r1_value) r2.register = BitVector(bitlist=r2_value) r3.register = BitVector(bitlist=r3_value) return r1, r2, r3
def encrypt(filename, key): data = None with open(filename, 'rb') as file: data = file.read() lfsr = LFSR(x, key) self_sh = SelfShrinking(lfsr, 8 * len(data)) seq = self_sh.generate() with open('encrypt.txt', 'wb') as file: for i in range(0, len(seq), 8): # print(seq[i:i+8]) symb = ''.join(str(e) for e in seq[i:i + 8]) symb = int(symb, 2) symb = (symb ^ data[i // 8]).to_bytes(1, byteorder="big") file.write(symb)
def build_tree(self, w): """builds the probability tree from a weight distribution """ w_abs = np.abs(w) if sum(w_abs) != 1.: w_abs = w_abs / sum(w_abs) self.w = w_abs self.tree = np.zeros(w.shape) self._build_node(w_abs, 1) self.w_apx = extract_distribution(self.tree) n_levels = np.ceil(np.log2(len(w))) self.lfsr = [] for n in range(int(n_levels)): seed = np.random.randint(1, int(2**(self.lfsr_nbits - n) - 1)) self.lfsr.append(LFSR(self.lfsr_nbits - n, seed))
def __init__(self, key, frame_counter): """ Creates an A5/2 Object :param key: 64 bit Session Key :param frame_counter: 22 bit frame counter """ if not (key >= 0 and key < math.pow(2, KEY_SIZE)): raise ValueError('Key value must be between 0 and 2^64!') if not (frame_counter >= 0 and frame_counter < math.pow(2, FRAME_COUNTER_SIZE)): raise ValueError('Frame counter value must be between 0 and 2^22!') self.r1 = LFSR(R1_SIZE, [], R1_TAPS, R1_MAJORITY_BITS, R1_NEGATED_BIT) self.r2 = LFSR(R2_SIZE, [], R2_TAPS, R2_MAJORITY_BITS, R2_NEGATED_BIT) self.r3 = LFSR(R3_SIZE, [], R3_TAPS, R3_MAJORITY_BITS, R3_NEGATED_BIT) self.r4 = LFSR(R4_SIZE, R4_CLOCK_BITS, R4_TAPS, [], None) self.key = BitVector(size=KEY_SIZE, intVal=key) self.frame_counter = BitVector(size=FRAME_COUNTER_SIZE, intVal=frame_counter) self.key_stream = BitVector(size=KEY_STREAM_SIZE) self.register_states = []
def get_key_stream_with_predefined_registers(self, r1, r2, r3, r4, generate_only_send_key=False): """ Sets the registers to the specified values (r1, r2, r3 and r4) and calculates a key stream :param r1: register 1 LFSR :param r2: register 2 LFSR :param r3: register 3 LFSR :param r4: register 4 LFSR :param generate_only_send_key: generates only the first 114 bits. Useful for checking the correct register values in the attack :return the generated key stream """ self.r1 = LFSR(R1_SIZE, [], R1_TAPS, R1_MAJORITY_BITS, R1_NEGATED_BIT, bitstring=r1) self.r2 = LFSR(R2_SIZE, [], R2_TAPS, R2_MAJORITY_BITS, R2_NEGATED_BIT, bitstring=r2) self.r3 = LFSR(R3_SIZE, [], R3_TAPS, R3_MAJORITY_BITS, R3_NEGATED_BIT, bitstring=r3) self.r4 = LFSR(R4_SIZE, R4_CLOCK_BITS, R4_TAPS, [], None, bitstring=r4) self._clocking_with_majority(MAJORITY_CYCLES_A52) self._generate_key_stream(generate_only_send_key=generate_only_send_key) return (self.send_key, self.receive_key)
def __init__(self, key, frame_counter): """ Creates an A5/1 Object :param key: 64 bit Session Key :param frame_counter: 22 bit frame counter """ if not (key >= 0 and key < math.pow(2, KEY_SIZE)): raise ValueError('Key value must be between 0 and 2^64!') if not (frame_counter >= 0 and frame_counter < math.pow(2, FRAME_COUNTER_SIZE)): raise ValueError('Frame counter value must be between 0 and 2^22!') self.r1 = LFSR(R1_SIZE, [R1_CLOCKING_BIT], R1_TAPS) self.r2 = LFSR(R2_SIZE, [R2_CLOCKING_BIT], R2_TAPS) self.r3 = LFSR(R3_SIZE, [R3_CLOCKING_BIT], R3_TAPS) self.key = BitVector(size=KEY_SIZE, intVal=key) self.frame_counter = BitVector(size=FRAME_COUNTER_SIZE, intVal=frame_counter) self.key_stream = BitVector(size=KEY_STREAM_SIZE) self._clocking(KEY_SIZE, self.key) self._clocking(FRAME_COUNTER_SIZE, self.frame_counter) self._clocking_with_majority(MAJORITY_CYCLES_A51) self._generate_key_stream()
from lfsr import LFSR from constants import polys import itertools def nth(iterable, nth): return next(itertools.islice(iterable, nth, nth + 1)) def search(poly, cipher): i = 0 lfsr = LFSR(poly) while (next(lfsr) != cipher): i += 1 return i p = 7 x = 8421 delta = -376 u = nth(LFSR(polys[p]), x) v = nth(LFSR(polys[p]), x + delta) print(u, v) candidates = sorted([(k, abs(search(poly, u) - search(poly, v))) for k, poly in enumerate(polys)], key=lambda x: x[0])
symb = (symb ^ data[i // 8]).to_bytes(1, byteorder="big") file.write(symb) if __name__ == "__main__": x = 2**64 + 27 # многочлен s = 9348798729764 # начальное заполнение (пароль) print( 'Выберите действие:\n\t1. Сгенерировать последовательность при помощи самосжимающего генератора' '\n\t2. Зашифровать файл при помощи поточной криптосистемы с использованием гаммы' ) choose = int(input("<<")) if choose == 1: L = int(input('введите длину последовательности: ')) lfsr = LFSR(x, s) self_sh = SelfShrinking(lfsr, L) res = self_sh.generate() print(' --- Сгенерированная последовательнось ---\n', res, '\n\nпоследовательность записана в файл seq.txt') with open('seq.txt', 'w') as file: cnt = 0 for item in res: file.write("%s " % item) if cnt == 79: file.write("\n") cnt = 1 else: cnt += 1 elif choose == 2: filename = input("Введите имя файла: ")
from PIL import Image from lfsr import LFSR from functools import reduce from feedback import feedback_poly, one_hot_encode lfsr = LFSR(15, 'gal', [1 for _ in range(15)]) s = "" ints = lfsr.encrypt_decrypt_ints() value = 0 im = Image.open(r"yoda.png") px = im.load() print(px[0, 0]) width, height = im.size print("Height :", height, " And width : ", width) for i in range(width): for j in range(height): r, g, b, temp = px[i, j] r = (r) ^ ints[value] value = (value + 1) % (len(ints)) g = (g) ^ ints[value] value = (value + 1) % (len(ints)) b = (b) ^ ints[value] value = (value + 1) % (len(ints)) temp = (temp) ^ ints[value] value = (value + 1) % (len(ints)) px[i, j] = (r, g, b, temp) im.show() im.save("output.png")
class A5_2(object): """ Represents the A5/2 stream cipher. A key stream for a given session key and the corresponding frame counter can be generated """ def __init__(self, key, frame_counter): """ Creates an A5/2 Object :param key: 64 bit Session Key :param frame_counter: 22 bit frame counter """ if not (key >= 0 and key < math.pow(2, KEY_SIZE)): raise ValueError('Key value must be between 0 and 2^64!') if not (frame_counter >= 0 and frame_counter < math.pow(2, FRAME_COUNTER_SIZE)): raise ValueError('Frame counter value must be between 0 and 2^22!') self.r1 = LFSR(R1_SIZE, [], R1_TAPS, R1_MAJORITY_BITS, R1_NEGATED_BIT) self.r2 = LFSR(R2_SIZE, [], R2_TAPS, R2_MAJORITY_BITS, R2_NEGATED_BIT) self.r3 = LFSR(R3_SIZE, [], R3_TAPS, R3_MAJORITY_BITS, R3_NEGATED_BIT) self.r4 = LFSR(R4_SIZE, R4_CLOCK_BITS, R4_TAPS, [], None) self.key = BitVector(size=KEY_SIZE, intVal=key) self.frame_counter = BitVector(size=FRAME_COUNTER_SIZE, intVal=frame_counter) self.key_stream = BitVector(size=KEY_STREAM_SIZE) self.register_states = [] def get_key_stream_with_predefined_registers(self, r1, r2, r3, r4, generate_only_send_key=False): """ Sets the registers to the specified values (r1, r2, r3 and r4) and calculates a key stream :param r1: register 1 LFSR :param r2: register 2 LFSR :param r3: register 3 LFSR :param r4: register 4 LFSR :param generate_only_send_key: generates only the first 114 bits. Useful for checking the correct register values in the attack :return the generated key stream """ self.r1 = LFSR(R1_SIZE, [], R1_TAPS, R1_MAJORITY_BITS, R1_NEGATED_BIT, bitstring=r1) self.r2 = LFSR(R2_SIZE, [], R2_TAPS, R2_MAJORITY_BITS, R2_NEGATED_BIT, bitstring=r2) self.r3 = LFSR(R3_SIZE, [], R3_TAPS, R3_MAJORITY_BITS, R3_NEGATED_BIT, bitstring=r3) self.r4 = LFSR(R4_SIZE, R4_CLOCK_BITS, R4_TAPS, [], None, bitstring=r4) self._clocking_with_majority(MAJORITY_CYCLES_A52) self._generate_key_stream(generate_only_send_key=generate_only_send_key) return (self.send_key, self.receive_key) def _create_register_backup(self): """ Saves the register states r1, r2, r3 and r4 in a dictionary """ self.initial_sates = {'r1': copy.deepcopy(self.r1), 'r2': copy.deepcopy(self.r2), 'r3': copy.deepcopy(self.r3), 'r4': copy.deepcopy(self.r4)} def _set_bits(self): """ Sets the bits R1[15] = 1, R2[16] = 1, R3[18] = 1, R4[10] = 1. """ self.r1.set_bit(FORCE_R1_BIT_TO_1, 1) self.r2.set_bit(FORCE_R2_BIT_TO_1, 1) self.r3.set_bit(FORCE_R3_BIT_TO_1, 1) self.r4.set_bit(FORCE_R4_BIT_TO_1, 1) def _clocking(self, limit, vector): """ Performs clocking for all registers (r1, r2, r3 and r4) :param limit: number of clocking cycles :param vector: either the session key or the frame counter. In each cycle a bit is XORed to the first position. """ for i in reversed(range(limit)): self.r1.clock(vector[i]) self.r2.clock(vector[i]) self.r3.clock(vector[i]) self.r4.clock(vector[i]) def _clocking_with_majority(self, limit, generate_key_stream=False, save_register_states=False): """ Performs clocking for the registers r1, r2 and r3 with the majority function of r4 :param limit: number of clocking cycles :param generate_key_stream: Boolean, which determines whether the output bits should be discarded :param save_register_states: Flag, that indicates whether the register states in each clock cycle should be saved """ for i in range(limit): majority = self._majority() if self.r4.get_bit(R4_CLOCKING_BIT_FOR_R1) == majority: self.r1.clock() if self.r4.get_bit(R4_CLOCKING_BIT_FOR_R2) == majority: self.r2.clock() if self.r4.get_bit(R4_CLOCKING_BIT_FOR_R3) == majority: self.r3.clock() self.r4.clock() if generate_key_stream: if save_register_states: self.register_states.append({'r1': copy.deepcopy(self.r1), 'r2': copy.deepcopy(self.r2), 'r3': copy.deepcopy(self.r3)}) self._add_key_stream_bit(i) def _generate_key_stream(self, save_register_states=False, generate_only_send_key=False): """ Generates 114 bits for the send key and 114 bits for the receive key. """ self._clocking_with_majority(KEY_STREAM_SIZE, save_register_states=save_register_states, generate_key_stream=True) if not generate_only_send_key: self.send_key = self.key_stream.deep_copy() self._clocking_with_majority(KEY_STREAM_SIZE, save_register_states=save_register_states, generate_key_stream=True) self.receive_key = self.key_stream.deep_copy() else: self.send_key = self.key_stream self.receive_key = None def get_key_stream(self, save_register_states=False, generate_only_send_key=False): """ Performs the following steps: 1. Run A5/2 for 64 cycles and XOR the session key into the registers 2. Run A5/2 for 22 cycles and XOR the frame counter into the registers 3. Sets the bits R1[15] = 1, R2[16] = 1, R3[18] = 1, R4[10] = 1. 4. Run A5/2 for 99 cycles and discard the output 5. Run A5/2 for 228 cycles and use the output as key stream :param save_register_states: Flag, that indicates whether the register states in each clock cycle should be saved :return key stream as pair (send_key, receive_key) """ self._clocking(KEY_SIZE, self.key) self._clocking(FRAME_COUNTER_SIZE, self.frame_counter) self._set_bits() self._create_register_backup() self._clocking_with_majority(MAJORITY_CYCLES_A52) self._generate_key_stream(save_register_states, generate_only_send_key=generate_only_send_key) return (self.send_key, self.receive_key) def _add_key_stream_bit(self, index): """ Calculates the output bit (key bit) :param index: The key stream bit index """ self.key_stream[index] = self.r1.register[0] ^ self.r2.register[0] ^ self.r3.register[0] ^ self.r1.get_majority() ^ self.r2.get_majority() ^ self.r3.get_majority() def _majority(self): """ :return most common bit in R4 """ clocked_bits = [] clocked_bits = clocked_bits + self.r4.get_clock_bits() a = clocked_bits[0] b = clocked_bits[1] c = clocked_bits[2] return (a*b) ^ (a*c) ^ (b*c)
import numpy as np from lfsr import LFSR ## Example 1 ## 5 bit LFSR with x^5 + x^2 + 1 L = LFSR() L.info() L.next() L.runKCycle(10) L.runFullCycle() L.info() tempseq = L.runKCycle(10000) # generate 10000 bits from current state ## Example 2 ## 5 bit LFSR with custum state and feedback polynomial state = np.array([0, 0, 0, 1, 0]) fpoly = [5, 4, 3, 2] L = LFSR(fpoly=fpoly, initstate=state, verbose=True) L.info() tempseq = L.runKCycle(10) tempseq L.set(fpoly=[5, 3]) ## Example 3 ## 23 bit LFSR with custum state and feedback polynomial L = LFSR(fpoly=[23, 19], initstate='ones', verbose=True) L.info() L.runKCycle(10) L.info() seq = L.seq L.changeFpoly(newfpoly=[23, 21]) seq1 = L.runKCycle(20)
def search(poly, cipher): i = 0 lfsr = LFSR(poly) while (next(lfsr) != cipher): i += 1 return i
import numpy as np from lfsr import LFSR ## Example 1 ## 5 bit LFSR with x^5 + x^2 + 1 # L = LFSR() # L.info() # L.next() # L.runKCycle(10) # L.runFullCycle() # L.info() # tempseq = L.runKCycle(10000) # generate 10000 bits from current state # state = np.array([0,0,0,1,0]) # fpoly = [5,4,3,2] # L = LFSR(fpoly=fpoly,initstate =state, verbose=True) # L.info() # tempseq = L.runKCycle(10) # tempseq # L.set(fpoly=[5,3]) ## Example 3 ## 23 bit LFSR with custum state and feedback polynomial state = np.array([0, 0, 0, 1, 1, 0, 1, 0, 0]) L = LFSR(fpoly=[8,6,5,4],initstate =state,verbose=True) L.info() seq = L.runKCycle(30)
def main(): inp = LFSR(12345,[1,6,8]).output(50) loc, len_ = Berlekamp_Massey_algorithm(inp) print([i+1 for i in list(loc)[:-1]], len_)
class A5_1(object): """ Represents the A5/1 stream cipher. A key stream for a given session key and the corresponding frame counter can be generated """ def __init__(self, key, frame_counter): """ Creates an A5/1 Object :param key: 64 bit Session Key :param frame_counter: 22 bit frame counter """ if not (key >= 0 and key < math.pow(2, KEY_SIZE)): raise ValueError('Key value must be between 0 and 2^64!') if not (frame_counter >= 0 and frame_counter < math.pow(2, FRAME_COUNTER_SIZE)): raise ValueError('Frame counter value must be between 0 and 2^22!') self.r1 = LFSR(R1_SIZE, [R1_CLOCKING_BIT], R1_TAPS) self.r2 = LFSR(R2_SIZE, [R2_CLOCKING_BIT], R2_TAPS) self.r3 = LFSR(R3_SIZE, [R3_CLOCKING_BIT], R3_TAPS) self.key = BitVector(size=KEY_SIZE, intVal=key) self.frame_counter = BitVector(size=FRAME_COUNTER_SIZE, intVal=frame_counter) self.key_stream = BitVector(size=KEY_STREAM_SIZE) self._clocking(KEY_SIZE, self.key) self._clocking(FRAME_COUNTER_SIZE, self.frame_counter) self._clocking_with_majority(MAJORITY_CYCLES_A51) self._generate_key_stream() def _clocking(self, limit, vector): """ Performs clocking for all registers (r1, r2 and r3) :param limit: number of clocking cycles :param vector: either the session key or the frame counter. In each cycle a bit is XORed to the first position. """ for i in reversed(range(limit)): self.r1.clock(vector[i]) self.r2.clock(vector[i]) self.r3.clock(vector[i]) def _clocking_with_majority(self, limit, generate_key_stream=False): """ Performs clocking for the registers r1, r2 and r3 :param limit: number of clocking cycles :param generate_key_stream: Boolean, which determines whether the output bits should be discarded """ for i in range(limit): majority = self._majority() if self.r1.get_clock_bits()[0] == majority: self.r1.clock() if self.r2.get_clock_bits()[0] == majority: self.r2.clock() if self.r3.get_clock_bits()[0] == majority: self.r3.clock() if generate_key_stream: self._add_key_stream_bit(i) def _generate_key_stream(self): """ Generates 114 bits for the send key and 114 bits for the receive key. """ self._clocking_with_majority(KEY_STREAM_SIZE, True) self.send_key = self.key_stream.deep_copy() self._clocking_with_majority(KEY_STREAM_SIZE, True) self.receive_key = self.key_stream.deep_copy() def get_key_stream(self): return (self.send_key, self.receive_key) def _add_key_stream_bit(self, index): """ Calculates the output bit (key bit) :param index: The key stream bit index """ self.key_stream[index] = self.r1.register[0] ^ self.r2.register[ 0] ^ self.r3.register[0] def _majority(self): """ :return most common bit of the clocking bits from r1, r2 and r3 """ clocked_bits = [] clocked_bits.append(self.r1.get_clock_bits()[0]) clocked_bits.append(self.r2.get_clock_bits()[0]) clocked_bits.append(self.r3.get_clock_bits()[0]) counter = Counter(clocked_bits) return counter.most_common(1)[0][0]