README + comments

This commit is contained in:
Sam Hadow 2024-04-26 12:11:26 +02:00
parent 3f661dab69
commit aa9e11caed
2 changed files with 26 additions and 5 deletions

View File

@ -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
View File

@ -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")