README + comments
This commit is contained in:
parent
3f661dab69
commit
aa9e11caed
12
README.md
12
README.md
@ -1,2 +1,14 @@
|
||||
# IN603
|
||||
|
||||
attack against Content Scrambling System cipher
|
||||
|
||||
|
||||
### execution
|
||||
|
||||
```
|
||||
python main.py
|
||||
```
|
||||
+ 17 bits lfsr check
|
||||
+ 0xffffffffff encryption and decryption test
|
||||
+ testing attack in 2^16 with 6 output bytes provided against CSS n times (by default 5), with keys randomly generated
|
||||
+ testing safer attack (same as above but use a 7th byte in case of a collision between 2 keys with 6 output bytes)
|
||||
|
19
main.py
19
main.py
@ -5,8 +5,11 @@ import multiprocessing
|
||||
|
||||
class lfsr(object):
|
||||
def __init__(self, state, taps):
|
||||
self.state = state
|
||||
self.taps = taps
|
||||
if max(taps) > len(state):
|
||||
raise ValueError("inconsistent taps and initial state")
|
||||
else:
|
||||
self.state = state
|
||||
self.taps = taps
|
||||
|
||||
# getters and setters (private attributes)
|
||||
def get_state(self):
|
||||
@ -104,25 +107,30 @@ def attack_worker(start, end, Bytes, result_queue, stop_event):
|
||||
taps17 = [0, 14]
|
||||
taps25 = [0, 3, 4, 12]
|
||||
for i in range(start, end):
|
||||
if stop_event.is_set():
|
||||
if stop_event.is_set(): # stop key search as soon as one worker finds a solution
|
||||
return
|
||||
lfsr17_init = [int(bit) for bit in bin(i)[2:].zfill(16)]+[1]
|
||||
lfsr17 = lfsr(lfsr17_init, taps17)
|
||||
x = []
|
||||
# generate first 3 output bytes from lfsr 17
|
||||
for _ in range(3):
|
||||
x_bin = ""
|
||||
for _ in range(8):
|
||||
x_bin += str(lfsr17.shift())
|
||||
x.append(int(x_bin[::-1], 2))
|
||||
# calculate corresponding output bytes from lfsr 25
|
||||
y = [(Bytes[0]-x[0])%256]
|
||||
c=1 if x[0]+y[0]>255 else 0
|
||||
y.append((Bytes[1]-(x[1]+c))%256)
|
||||
c=1 if x[1]+y[1]>255 else 0
|
||||
y.append((Bytes[2]-(x[2]+c))%256)
|
||||
|
||||
lfsr25_init = [int(bit) for bit in (bin(y[0])[2:].zfill(8)[::-1] + bin(y[1])[2:].zfill(8)[::-1] + bin(y[2])[2:].zfill(8)[::-1] ) ]+[1]
|
||||
lfsr25 = lfsr(lfsr25_init, taps25)
|
||||
# first 3 bytes from lfsr 25 are already known
|
||||
for _ in range(24):
|
||||
lfsr25.shift()
|
||||
# generate next 3 bytes from lfsr 25 and lfsr 17
|
||||
for _ in range(3):
|
||||
x_bin = ""
|
||||
y_bin = ""
|
||||
@ -131,13 +139,14 @@ def attack_worker(start, end, Bytes, result_queue, stop_event):
|
||||
y_bin += str(lfsr25.shift())
|
||||
x.append(int(x_bin[::-1], 2))
|
||||
y.append(int(y_bin[::-1], 2))
|
||||
# check if we can generate the next 3 output bytes z4,z5,z6 correctly
|
||||
c=1 if x[2]+y[2]>255 else 0
|
||||
z4 = (x[3]+y[3]+c)%256
|
||||
c=1 if x[3]+y[3]>255 else 0
|
||||
z5 = (x[4]+y[4]+c)%256
|
||||
c=1 if x[4]+y[4]>255 else 0
|
||||
z6 = (x[5]+y[5]+c)%256
|
||||
if z4 == Bytes[3] and z5 == Bytes[4] and z6 == Bytes[5]:
|
||||
if z4 == Bytes[3] and z5 == Bytes[4] and z6 == Bytes[5]: # if these bytes are correct the key found is most likely the correct one
|
||||
key = bin(x[0])[2:].zfill(8)[::-1] + bin(x[1])[2:].zfill(8)[::-1] + bin(y[0])[2:].zfill(8)[::-1] + bin(y[1])[2:].zfill(8)[::-1] + bin(y[2])[2:].zfill(8)[::-1]
|
||||
result_queue.put(key)
|
||||
stop_event.set()
|
||||
@ -387,7 +396,7 @@ print("\n")
|
||||
# time to test attack with 100 keys
|
||||
# CPU: 6 cores at 3.8GHz
|
||||
# ~65 seconds
|
||||
test_attack(10)
|
||||
test_attack(5)
|
||||
print("\n")
|
||||
test_fail()
|
||||
print("\n")
|
||||
|
Loading…
x
Reference in New Issue
Block a user