-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsolve.py
65 lines (48 loc) · 1.3 KB
/
solve.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
#!/usr/bin/env python
from z3 import *
filename = "map1.txt"
filename = "map2.txt"
with open(filename, 'r') as f:
cipher, chalbox = eval(f.read())
length, gates, check = chalbox
# Create bit vectors
b = []
total_length = check[0] + 1
for count in range(total_length):
b.append(BitVec(str(count), 1))
# verify() constraints
s = Solver()
for i, (name, args) in enumerate(gates):
position = i + length
if name == 'true':
# b.append(1)
s.add(b[position] == 1)
else:
u1 = b[args[0][0]] ^ args[0][1]
u2 = b[args[1][0]] ^ args[1][1]
if name == 'or':
# b.append(u1 | u2)
s.add(b[position] == (u1 | u2))
elif name == 'xor':
# b.append(u1 ^ u2)
s.add(b[position] ==(u1 ^ u2))
else:
raise Exception("unknown gate")
s.add((b[check[0]] ^ check[1]) == 1)
# Solve
# https://z3prover.github.io/api/html/classz3py_1_1_model_ref.html
if s.check():
m = s.model()
sequence = ''
key = 0
for item in b:
name = str(item)
value = str(m[item])
# print(name, value)
sequence += value
bit_pos = int(name)
value = int(value)
if bit_pos < length:
key |= value << bit_pos
print 'sequence', sequence
print 'key', key