Commit 1bc9e959 authored by w3challs's avatar w3challs
Browse files

Added Singularity II & CurveFair

parent e563c163
# docker build . -t curvefair:latest
# docker run --restart=always -p 7781:7781 -itd --name curvefair curvefair:latest
FROM "sagemath/sagemath"
COPY server.sage /home/sage
EXPOSE 7781
ENTRYPOINT ["/home/sage/server.sage"]
#!/usr/bin/env sage
#-*- coding:utf-8 -*-
##################################################################
## Run with: sage /path/to/server.sage ##
##################################################################
import sys
import threading
import datetime
import time
import json
from hashlib import sha256
from socket import *
from time import gmtime
PORT = 7781
HOST = "0.0.0.0"
FLAG = "W3C{This is not the real flag}"
STARTING_BALANCE = 20
FLAG_BALANCE = 1000000
# ----------------------------------------------------------------
# SERVICE
# ----------------------------------------------------------------
def main():
serve()
def serve():
s = socket(AF_INET, SOCK_STREAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
print("[*] Server started on port {}".format(PORT))
while True:
conn, addr = s.accept()
thread = threading.Thread(None, serve_client, None, (conn,))
thread.start()
def serve_client(conn):
t1 = int(time.time())
context = {"balance": STARTING_BALANCE, "h": 0, "k": 0, "Gx": 0}
send_welcome(conn)
gen_setup(context)
send_setup(context, conn)
while True:
try:
send_info(context, conn)
data = conn.recv(1024).decode('ascii')
if (int(time.time()) - t1) > 60 * 60:
conn.sendall("Timeout\n".encode())
break
if data == "" or data == "\n" or not client(context, data, conn):
break
except:
conn.sendall("Invalid input\n".encode())
break
conn.close()
def client(context, data, conn):
print("[*] Received message {}".format(data))
command = data.strip()
conn.sendall(("*" * 65 + "\n").encode())
if command == "flag":
if context['balance'] >= FLAG_BALANCE:
conn.sendall("Congratulations! The flag is {}\n".format(FLAG).encode())
return False
else:
conn.sendall("You don't have enough credits to claim the flag\n".encode())
elif command == "reveal":
conn.sendall(reveal_setup(context).encode())
return False
elif command.startswith("bet"):
amount,guess = map(int,command.split(" ")[1:])
if amount <= 0:
conn.sendall("You must bet at least 1 credit\n".encode())
return False
if amount > context['balance']:
conn.sendall("You cannot bet more than your balance\n".encode())
return False
if guess > 15 or guess < 0:
conn.sendall("The number must be between 0 and 15 included\n".encode())
return True
context['balance'] -= amount
conn.sendall("You bet {} credits on the number {}...".format(amount,guess).encode())
next_draw = draw(context['Gx'],context['h'])
context['h'] += 1
if next_draw == guess:
conn.sendall("and you WIN!\n".encode())
context['balance'] += 2 * amount
else:
conn.sendall("and you LOST(the number was {})\n".format(next_draw).encode())
else:
conn.sendall("Unknown command\n".encode())
if context['balance'] == 0:
conn.sendall("You have no credits left\n".encode())
conn.sendall(reveal_setup(context).encode())
return False
return True
def send_welcome(conn):
ltime = gmtime()
out = "*" * 65 + "\n";
out += "**** Welcome to CurveFair ****\n"
out += "** This is a provably fair (tm) online casino **\n"
out += "** Place bets and guess the correct numbers to win the jackpot !**\n"
out += "** Reference time: {}h {}m {}s\n".format(ltime.tm_hour,ltime.tm_min,ltime.tm_sec)
out += "*" * 65 + "\n"
conn.sendall(out.encode())
def send_setup(context, conn):
out = "** To make sure we don't cheat you, we commit to a starting point P\n"
out += "** Starting point P = \n({},\n{})\n".format(context['P'][0],context['P'][1])
out += "** The intermediate parameters will be revealed later\n"
conn.sendall(out.encode())
def send_info(context,conn):
out = "*" * 65 + "\n"
out += "** Current balance: {} credits\n".format(context["balance"])
out += "** Commands:\n"
out += "* bet <c> <guess>: place a bet of <c> credits on number <guess>\n"
out += "* reveal: reveal the setup (ends the game)\n"
out += "* flag: claim the flag (balance above {} needed)\n".format(FLAG_BALANCE)
out += "*" * 65 + "\n"
conn.sendall(out.encode())
def reveal_setup(context):
out = "*" * 65 + "\n"
out += "** These are the parameters you can use to check the numbers **\n"
out += "k = {}\nGx = {}\n".format(context['k'],context['Gx'])
return out
# ----------------------------------------------------------------
# CRYPTO
# ----------------------------------------------------------------
p = 77842779395507334601861224827415108072619674595753802017004887970581678343527
a = 1
b = 288
n = 77842779395507334601861224827415108072392768534638711469554482491179480329427
def gen_setup(context):
E = EllipticCurve(GF(p),[a,b])
#assert n == E.cardinality()
P = E.random_point()
ltime = gmtime()
yd = ltime.tm_yday + 1
md = ltime.tm_mday + 2
wd = ltime.tm_wday + 3
h = ltime.tm_hour + 4
m = ltime.tm_min + 5
s = ltime.tm_sec + 6
mo = ltime.tm_mon + 7
y = ltime.tm_year + 8
Q = (mo * yd * md * (s // wd + 1) * (y // h ) * (n // m)) * P
k = randint(2,n-1)
G = k * Q
context['P'] = P
context['k'] = int(k)
context['Gx'] = int(G[0])
def draw(Gx,h):
return int(sha256("{}:{}".format(Gx,h).encode()).hexdigest()[-1], 16)
if __name__ == "__main__":
main()
#!/usr/bin/python2
#######################################################################
#
# credits to Lis - elliptic curve code taken from
# https://bitcointalk.org/index.php?topic=23241.0
#
#######################################################################
class CurveFp( object ):
def __init__( self, p, a, b ):
self.__p = p
self.__a = a
self.__b = b
def p( self ):
return self.__p
def a( self ):
return self.__a
def b( self ):
return self.__b
def contains_point( self, x, y ):
return ( y * y - ( x * x * x + self.__a * x + self.__b ) ) % self.__p == 0
class Point( object ):
def __init__( self, curve, x, y, order = None ):
self.__curve = curve
self.__x = x
self.__y = y
self.__order = order
if self.__curve: assert self.__curve.contains_point( x, y )
if order: assert self * order == INFINITY
def __add__( self, other ):
if other == INFINITY: return self
if self == INFINITY: return other
assert self.__curve == other.__curve
if self.__x == other.__x:
if ( self.__y + other.__y ) % self.__curve.p() == 0:
return INFINITY
else:
return self.double()
p = self.__curve.p()
l = ( ( other.__y - self.__y ) * \
inverse_mod( other.__x - self.__x, p ) ) % p
x3 = ( l * l - self.__x - other.__x ) % p
y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
return Point( self.__curve, x3, y3 )
def __mul__( self, other ):
def leftmost_bit( x ):
assert x > 0
result = 1L
while result <= x: result = 2 * result
return result / 2
e = other
if self.__order: e = e % self.__order
if e == 0: return INFINITY
if self == INFINITY: return INFINITY
assert e > 0
e3 = 3 * e
negative_self = Point( self.__curve, self.__x, -self.__y, self.__order )
i = leftmost_bit( e3 ) / 2
result = self
while i > 1:
result = result.double()
if ( e3 & i ) != 0 and ( e & i ) == 0: result = result + self
if ( e3 & i ) == 0 and ( e & i ) != 0: result = result + negative_self
i = i / 2
return result
def __rmul__( self, other ):
return self * other
def __str__( self ):
if self == INFINITY: return "infinity"
return "(%d,%d)" % ( self.__x, self.__y )
def __eq__(self, other):
return self.x() == other.x() and self.y() == other.y()
def double( self ):
if self == INFINITY:
return INFINITY
p = self.__curve.p()
a = self.__curve.a()
l = ( ( 3 * self.__x * self.__x + a ) * \
inverse_mod( 2 * self.__y, p ) ) % p
x3 = ( l * l - 2 * self.__x ) % p
y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
return Point( self.__curve, x3, y3 )
def x( self ):
return self.__x
def y( self ):
return self.__y
def curve( self ):
return self.__curve
def order( self ):
return self.__order
def inverse_mod( a, m ):
if a < 0 or m <= a: a = a % m
c, d = a, m
uc, vc, ud, vd = 1, 0, 0, 1
while c != 0:
q, c, d = divmod( d, c ) + ( c, )
uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vc
assert d == 1
if ud > 0: return ud
else: return ud + m
INFINITY = Point( None, None, None )
#######################################################################
#
# Lis' code ends here
#
#######################################################################
{"a": 213470994364689211866577105206, "p": 213470994364689211866577105207, "creation_time": 1588159568, "b": 0, "q": 26683874295586151483322138151, "Ay": 33699703931891629444312576020, "Ax": 45821310642463165379779158108, "expiration_time": 1588245968, "Bx": 104813781055353500032047462411, "By": 29403597840285420845784264893}
\ No newline at end of file
#!/usr/bin/python2
#-*- coding:utf-8 -*-
import threading
import datetime
import time
import json
from hashlib import sha256
from ecc import CurveFp, Point
from socket import *
PORT = 7780
HOST = "0.0.0.0"
FLAG = "W3C{This is not the real flag}"
# ----------------------------------------------------------------
# SERVICE
# ----------------------------------------------------------------
def main():
serve()
def serve():
s = socket(AF_INET, SOCK_STREAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
print "[*] Server started on port %d" % PORT
while True:
conn, addr = s.accept()
thread = threading.Thread(None, serve_client, None, (conn,))
thread.start()
def serve_client(conn):
try:
params = read_params()
send_params(params, conn)
except Exception as e:
print str(e)
conn.sendall("Invalid params, please alert an admin\n")
t1 = int(time.time())
while True:
try:
data = conn.recv(1024)
if (int(time.time()) - t1) > 60 * 10:
conn.sendall("Timeout\n")
break
if data == "" or not client(params, data, conn):
break
except:
conn.sendall("Invalid format\n")
break
conn.close()
def client(params, data, conn):
print "[*] Received message %s" % data
message, S, E = data.strip().split(",")
s,e = int(S),int(E)
if check_sig(params, message, s, e):
conn.sendall("Good signature\n")
if message == "Gimme the flag!":
conn.sendall("Congratulations! The flag is %s\n" % FLAG)
return False
else:
conn.sendall("Bad signature\n")
return False
return True
def read_params():
with open("params.json", "rb") as f:
params = json.loads(f.read())
return params
def send_params(params, conn):
out = "Current params (regenerated every 24 hours):\n"
for key in ("p", "a", "b", "q", "Ax", "Ay", "Bx", "By"):
out += " {} = {}\n".format(key, params[key])
now = int(time.time())
creation_delta = now - params['creation_time']
expiration_delta = params['expiration_time'] - now
if expiration_delta < 0 or creation_delta < 0:
raise Exception('Invalid params')
out += "Params were created {} ago and will expire in {}.\n".format(
datetime.timedelta(seconds=creation_delta),
datetime.timedelta(seconds=expiration_delta),
)
out += "-" * 65 + "\n"
conn.sendall(out)
# ----------------------------------------------------------------
# CRYPTO
# ----------------------------------------------------------------
def hash(m):
HASH_L = 22
return int(sha256(m).hexdigest()[:HASH_L], 16)
def hash_combine(P,m):
return hash(str(P.x()) + ':' + str(P.y()) + ':' + m)
def check_sig(params, m, s, e):
E = CurveFp(params['p'], params['a'], params['b'])
assert s < params['q']
assert e < params['q']
A = Point(E, params['Ax'], params['Ay'])
B = Point(E, params['Bx'], params['By'])
R = s*A + e*B
e_check = hash_combine(R,m)
return e_check == e
if __name__ == "__main__":
main()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment