-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchallenge4.py
More file actions
executable file
·144 lines (112 loc) · 4.25 KB
/
challenge4.py
File metadata and controls
executable file
·144 lines (112 loc) · 4.25 KB
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
from twisted.web.server import Site, Session
from twisted.web.resource import Resource
from twisted.internet import reactor
import random
import json
class LongSession (Session):
sessionTimeout = 10
class Challenge4(Resource):
sessions = set()
solution = ''
session = None
def get_answer(self, challenge):
# must drop answer in JSON file
answers = open('answers.json')
data = json.load(answers)
answers.close()
return str(data[challenge])
def generate_logic_equation(self):
# returns a tuple with the logic equation as string and solution as int (0 or 1)
# TODO add NOR and XNOR
logic_types = ['XOR', 'OR', 'NAND', 'AND']
equation = []
random.seed()
num_operations = random.randint(3, 7)
solution = 0
for i in range(num_operations):
if (i == 0):
# generate a new left operand
left = random.randint(0, 1)
equation.append(str(left))
else:
left = solution
# generate a new right operand
# TODO add NOT, by flipping to add or not to the gen right bit, and inverting result if so
right = random.randint(0, 1)
# choose a logic operator, skip if last
if (i < num_operations):
new_gate = random.choice (logic_types)
else:
new_gate = ""
# keep track of solution
gate = logic_types.index(new_gate)
if (gate == 0):
solution = left ^ right
elif (gate == 1):
solution = left | right
elif (gate == 2):
solution = int (not (left & right))
elif (gate == 3):
solution = left & right
equation.append(new_gate)
equation.append(str(right))
equation = " ".join(equation)
#print "DBG: solution = " + str(solution) + " for " + equation
return equation, solution
def render_GET(self, request):
# setup session
self.session = request.getSession()
if self.session.uid not in self.sessions:
self.sessions.add(self.session.uid)
self.session.notifyOnExpire(lambda: self._expired(self.session.uid))
# generate equations
msg = ""
result = 0
for i in range (7):
eq, sol = self.generate_logic_equation ()
# update accumulator with binary result
result += (2 ** i ) * sol
# print "DBG: result = " + str(result)
msg += eq + "\n"
# add this check to while loop to handle corner cases, resulting byte should be within printable ascii range
if (result < 32):
result += 32
elif (result > 126):
result -= 1
# cast global solution as string
self.solution = str(chr(result))
#print "DBG: end solution as binary = " + str(bin(result))
#print "DBG: end solution as asciichar = " + str(chr(result))
return msg
def render_POST(self, request):
# check for session expiry
if self.session.uid not in self.sessions:
self.sessions.add(self.session.uid)
self.session.notifyOnExpire(lambda: self._expired(self.session.uid))
return 'Session timed out'
try:
answer = json.loads(request.content.getvalue())['answer']
except ValueError:
return 'You should be submitting as JSON'
print "DBG Submission: |" + answer + "|"
print "DBG Answer was: |" + self.solution + "|"
# check submitted answer
if answer == self.solution:
print "DBG: challenge solved"
return self.get_answer('challenge4')
else:
return 'wrong answer\n'
def _expired(self, uid):
try:
self.sessions.remove(uid)
except:
pass
# if __name__ == __main__
print "LOG: starting bit twiddling slash logic gate challenge"
rootResource = Resource()
rootResource.putChild("challenge4", Challenge4())
factory = Site(rootResource)
factory.sessionFactory = LongSession
reactor.listenTCP(8084, factory)
reactor.run()