This commit is contained in:
2023-11-24 18:19:13 +01:00
parent 41031cc6f8
commit 2a136311d0
2 changed files with 124 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
#!/usr/bin/env python3
from flask import Flask, Response, request, send_from_directory
from ecdsa import SigningKey, VerifyingKey, BadSignatureError
from base64 import b64decode, b64encode
from hashlib import sha256
from random import randrange
import os
import time
...
if not FLAG:
import sys
sys.exit(1)
app_dir = os.path.abspath(os.path.dirname(__file__))
admin_priv = SigningKey.from_pem(open('{}/keys/admin_priv.pem'.format(app_dir)).read(), hashfunc=sha256)
admin_pub = admin_priv.verifying_key
user_keys = dict()
for u in ['john', 'kate', 'silberman']:
user_keys[u] = VerifyingKey.from_pem(open('{}/keys/{}_pub.pem'.format(app_dir, u)).read(), hashfunc=sha256)
K_COEFF = [randrange(0, admin_pub.curve.order) for _ in range(5)]
chal_ts = None
chal_sig = None
chal_k = randrange(0, admin_pub.curve.order)
app = Flask(__name__, static_folder='{}/static'.format(app_dir))
...
def timestamp():
t = int(time.time())
return t - t % 30
def sigdecode(sig, order):
bl = (order.bit_length() + 7) // 8
sig = b64decode(sig.encode('utf-8'))
assert len(sig) == 2 * bl
r = int.from_bytes(sig[:bl], 'big')
s = int.from_bytes(sig[bl:], 'big')
return r % order, s % order
def sigencode(r, s, order):
bl = (order.bit_length() + 7) // 8
r = (r % order).to_bytes(bl, 'big')
s = (s % order).to_bytes(bl, 'big')
return b64encode(r + s).decode('utf-8')
def sigcheck(pubkey, sig):
try:
if pubkey.verify(sig, str(chal_ts).encode('utf-8') + b'login', hashfunc=sha256, sigdecode=sigdecode):
return True
except BadSignatureError:
pass
return False
@app.route('/static/<path:path>', methods=['GET'])
def serve_static(path):
return send_from_directory('static', path)
@app.route('/', methods=['GET'])
def index():
return app.send_static_file('index.html')
@app.route('/login', methods=['POST'])
def login():
data = request.get_json()
if 'user' not in data or 'sig' not in data:
return Response("Invalid request format", status=400)
user = data['user']
if user not in user_keys:
return { 'invalid': 'Invalid username' }
sig = data['sig']
if sigcheck(user_keys[user], sig) or sigcheck(admin_pub, sig):
return { 'valid': '{}'.format(FLAG) }
return { 'invalid': 'Invalid private key' }
@app.route('/challenge', methods=['GET'])
def challenge():
global chal_ts, chal_sig, chal_k
ts = timestamp()
if ts != chal_ts:
chal_ts = ts
chal_k = sum(a * chal_k ** i for i, a in enumerate(K_COEFF)) % admin_pub.curve.order
chal_sig = admin_priv.sign(str(chal_ts).encode('utf-8') + b'challenge', hashfunc=sha256, sigencode=sigencode, k=chal_k)
return { 'challenge': str(chal_ts), 'sig': chal_sig }
if __name__ == '__main__':
...