-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathserver.py
126 lines (99 loc) · 3.33 KB
/
server.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
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
import ctypes
import os
from hashlib import sha512
import signal
# libcsidh interop start
# modified from DiceCTF 2023 - seaside
PRIVATE_KEY_SIZE = 74
PUBLIC_KEY_SIZE = 64
MAX_EXPONENT = 5
# libcsidh: https://yx7.cc/code/csidh/csidh-latest.tar.xz
# Run this to build libcsidh: `(cd csidh-20210627; make; mv libcsidh.so ..)`
libcsidh = ctypes.CDLL("./libcsidh.so")
def apply_iso(start, iso):
end = ctypes.create_string_buffer(PUBLIC_KEY_SIZE)
ret = libcsidh.csidh(end, start, iso)
if not ret:
raise RuntimeError("csidh failed")
return end
def pub_from(buf):
return ctypes.create_string_buffer(buf, PUBLIC_KEY_SIZE)
def priv_from(es):
return ctypes.create_string_buffer(bytes([e & 0xFF for e in es]), PRIVATE_KEY_SIZE)
def rand_priv():
priv = ctypes.create_string_buffer(PRIVATE_KEY_SIZE)
libcsidh.csidh_private(priv)
return priv
def hash_to_priv(buf):
v = int(sha512(bytes(buf)).hexdigest(), 16)
es = []
M = 2 * MAX_EXPONENT + 1
for _ in range(PRIVATE_KEY_SIZE):
es.append(v % M - MAX_EXPONENT)
v //= M
return priv_from(es)
# libcsidh interop end
c1 = libcsidh.base
leet = [1, 3, 3, 7]
leet = (leet * (PRIVATE_KEY_SIZE // len(leet) + 1))[:PRIVATE_KEY_SIZE]
c2 = apply_iso(libcsidh.base, priv_from(leet))
class RNG:
def __init__(self, c1, c2, l, r):
self.c1 = c1
self.c2 = c2
self.l = l
self.r = r
self.c = 0
self.v = 0
self.trunc = 12
def next(self):
self.l, self.r = self.r, hash_to_priv(
apply_iso(apply_iso(self.c1, self.l), self.r)
)
return int.from_bytes(
bytes(apply_iso(apply_iso(self.c2, self.r), self.l)), "little"
)
def bit(self):
if self.c == 0:
self.v = self.next()
self.c = PUBLIC_KEY_SIZE * 8 - self.trunc
self.c -= 1
r = self.v & 1
self.v >>= 1
return r
class Game:
def __init__(self, rng):
self.rng = rng
self.money = 1337
self.win = 13337
def round(self):
bit = int(input("guess > "))
if bit == self.rng.bit():
self.money += 1
print("You win!")
else:
self.money -= 3
print("You lose!")
def play(self):
print("Welcome to Imaginary Casino!")
print(
"Immerse yourself in the captivating simplicity of Imaginary Casino, where a single game of coin flip becomes a thrilling quantum experience. Powered by a quantum-secure random number generator, every flip is truly unpredictable, ensuring an unparalleled level of fairness and excitement."
)
print(
f"You begin your journey at Imaginary Casino with an initial balance of ${self.money}, and as you progress, the grand flag awaits you once you reach the milestone of ${self.win}."
)
print("(Generated by ChatGPT)")
print()
while self.money > 0:
self.round()
print(f"You have ${self.money} left.")
if self.money >= self.win:
print("Here's your flag:")
with open("flag.txt") as f:
print(f.read().strip())
return
print("You're broke!")
if __name__ == "__main__":
signal.alarm(30)
rng = RNG(c1, c2, rand_priv(), rand_priv())
Game(rng).play()