#!/usr/bin/env python3 from random import randint from math import log2 class lfsr(object): def __init__(self, state, taps): self.state = state self.taps = taps # getters and setters (private attributes) def get_state(self): return self.__state def set_state(self, value): self.__state = value state = property(fget=get_state, fset=set_state, doc="lfsr state (current bits value in lfsr)") def get_taps(self): return self.__taps def set_taps(self, valeur): self.__taps = valeur taps = property(fget=get_taps, fset=set_taps, doc="lfsr taps (bit positions affecting next state)") def shift(self): ''' calculate next state and return the output bit ''' feedback = sum(self.state[tap] for tap in self.taps) % 2 output = self.state[0] self.state = self.state[1:] + [feedback] return output def test_lfsr17(): key = [randint(0, 1) for _ in range(16)] # first 16 bits key.append(1) # prevent initial state from being {0}^17 taps = [0, 14] lfsr17 = lfsr(key, taps) states = [lfsr17.state] for _ in range(2**17-2): lfsr17.shift() states.append(lfsr17.state) sorted_states = sorted(states, key=lambda x: tuple(x)) for i in range(2**17-2): if sorted_states[i] == sorted_states[i+1]: # compare each state with the next state in the sorted list, if 2 states are identical they should be next to each other print(f'state {sorted_states[i]} appears at least 2 times') return False n_state = len(sorted_states) n_state_log = log2(n_state+1) print(f'all {n_state} = 2^({n_state_log})-1 states are different') return True def css_encrypt(text, key): taps17 = [0, 14] lfsr17 = lfsr((key[:16]+[1]), taps17) taps25 = [0, 3, 4, 12] lfsr25 = lfsr((key[16:]+[1]), taps25) cipher_text = 0 carry = 0 bytes = text.to_bytes((text.bit_length() + 7) // 8, 'big') for byte in bytes: x_b2 = "" y_b2 = "" # Generate bytes from lfsr17 and lfsr25 for _ in range(8): x_b2 += str(lfsr17.shift()) y_b2 += str(lfsr25.shift()) x = int(x_b2, 2) y = int(y_b2, 2) z = (x + y + carry) % 256 carry = 1 if x + y > 255 else 0 cipher_byte = z ^ byte cipher_text = (cipher_text << 8) | cipher_byte return cipher_text test_lfsr17() cipher = css_encrypt(0xffffffffff, [0]*40) print(hex(cipher)) clear = css_encrypt(cipher, [0]*40) print(hex(clear))