-
Notifications
You must be signed in to change notification settings - Fork 1
/
lfsr.py
71 lines (64 loc) · 2.75 KB
/
lfsr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from BitVector import BitVector
class LFSR(object):
"""
This class represents a linear feedback shift register for
the A5 stream cipher
"""
def __init__(self, length, clock_bits, taps, majority_bits=None, negated_bit=None, bitstring=None, int_value=None):
"""
:param length: size (number of bits) of the lfsr
:param clock_bits: position of bits which indicate
clocking for A5/1
:param taps: position of bits to calculate the first
position in a clocking cycle
:param majority_bits: Optional parameter, positions of
bits for the majority function A5/2
:param negated_bit: Optional parameter, position of the
bit that is negated in the majority
function (for A5/2)
:param bitstring: register value as bitstring
:param int_value: register value as integer
"""
if bitstring:
self.register = BitVector(bitstring=bitstring)
elif int_value:
self.register = BitVector(size=length, intVal=int_value)
else:
self.register = BitVector(size=length)
self.length = length
self.taps = taps
self.majority_bits = majority_bits
self.negated_bit = negated_bit
self.clock_bits = []
for clock_bit in clock_bits:
self.clock_bits.append(length - clock_bit - 1)
def clock(self, key_bit=False):
"""
Clocks the lfsr
:param key_bit: Optional parameter for XORing
an additional bit into the first
position (relevant if frame counter
or session key is clocked into lfsr)
"""
result = key_bit
for tap in self.taps:
result = result ^ self.register[(self.length - tap - 1)]
self.register << 1
self.register[-1] = result
def get_clock_bits(self):
clock_bit_values = []
for clock_bit in self.clock_bits:
clock_bit_values.append(self.register[clock_bit])
return clock_bit_values
def set_bit(self, index, value):
self.register[self.length - index - 1] = value
def get_bit(self, index):
return self.register[self.length - index - 1]
def get_majority(self):
values = [self.register[self.length - self.negated_bit - 1] ^ 1]
for bit in self.majority_bits:
values.append(self.register[self.length - bit - 1])
a = values[0]
b = values[1]
c = values[2]
return (a*b) ^ (a*c) ^ (b*c)