Initial commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
from Crypto.Util.number import *
|
||||
from fastecdsa.curve import Curve
|
||||
from fastecdsa.point import Point
|
||||
from base64 import urlsafe_b64decode, urlsafe_b64encode
|
||||
from time import time
|
||||
from zlib import crc32
|
||||
|
||||
|
||||
class BurveSigner:
|
||||
def __init__(self):
|
||||
self.C = Curve(
|
||||
"burvesigner",
|
||||
0xDB7C2ABF62E35E668076BEAD208B,
|
||||
0xDB7C2ABF62E35E668076BEAD2088,
|
||||
0x659EF8BA043916EEDE8911702B22,
|
||||
0xDB7C2ABF62E35E7628DFAC6561C5,
|
||||
0x0E27CD305696E88F38F7EB1FBECE,
|
||||
0xCAA9A6F90944FAD41FBE02B8FD77,
|
||||
)
|
||||
self.t = self.C.p.bit_length() // 8
|
||||
self.u = self.C.p.bit_length() - 64
|
||||
self.v = getRandomNBitInteger(self.u)
|
||||
|
||||
def from_bytes(self, data):
|
||||
return int.from_bytes(data, "little")
|
||||
|
||||
def to_bytes(self, num):
|
||||
return int.to_bytes(num, self.t, "little")
|
||||
|
||||
def hash(self, msg):
|
||||
return crc32(msg)
|
||||
|
||||
def set_keys(self):
|
||||
priv = open("/priv.data", "rb").read()[:self.t]
|
||||
self.x = self.from_bytes(priv)
|
||||
self.Y = self.x * self.C.G
|
||||
|
||||
def get_params(self):
|
||||
self.set_keys()
|
||||
return {
|
||||
"p": self.C.p,
|
||||
"a": self.C.a,
|
||||
"b": self.C.b,
|
||||
"n": self.C.q,
|
||||
"G": (self.C.gx, self.C.gy),
|
||||
"Y": (self.Y.x, self.Y.y),
|
||||
}
|
||||
|
||||
def sign(self, msg):
|
||||
self.set_keys()
|
||||
k = (int(time() * 1337) << self.u) + self.v
|
||||
R = k * self.C.G
|
||||
s = (self.hash(msg) - self.x * R.x) * pow(k, -1, self.C.q) % self.C.q
|
||||
sig = b"".join(map(self.to_bytes, [R.x, R.y, s]))
|
||||
return urlsafe_b64encode(sig)
|
||||
|
||||
def verify(self, msg, sig):
|
||||
self.set_keys()
|
||||
try:
|
||||
assert len(sig) == 4 * self.t
|
||||
sig = urlsafe_b64decode(sig)
|
||||
arr = [sig[self.t * i : self.t * (i + 1)] for i in range(3)]
|
||||
Rx, Ry, s = map(self.from_bytes, arr)
|
||||
R = Point(Rx, Ry, self.C)
|
||||
return self.hash(msg) * self.C.G == s * R + self.Y * R.x
|
||||
except:
|
||||
return False
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
import sqlite3
|
||||
|
||||
db = "database.db"
|
||||
con = sqlite3.connect(db)
|
||||
cur = con.cursor()
|
||||
cur.execute("SELECT * FROM users")
|
||||
|
||||
rows = cur.fetchall()
|
||||
for row in rows:
|
||||
print(row)
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
import hashlib
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
|
||||
db = "database.db"
|
||||
|
||||
|
||||
class User:
|
||||
def __init__(self, username, password, role):
|
||||
self.username: str = username
|
||||
self.password: str = password
|
||||
self.role: str = role
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
os.remove(db)
|
||||
except:
|
||||
pass
|
||||
|
||||
con = sqlite3.connect(db)
|
||||
con.execute("CREATE TABLE users (username TEXT, password TEXT, role TEXT)")
|
||||
|
||||
def insert_person(person: User):
|
||||
cur.execute(
|
||||
"INSERT INTO users (username, password, role) VALUES (?, ?, ?)",
|
||||
(
|
||||
person.username,
|
||||
hashlib.sha256(
|
||||
b"gema" + person.password.encode() + b"steg"
|
||||
).hexdigest(),
|
||||
person.role,
|
||||
),
|
||||
)
|
||||
con.commit()
|
||||
|
||||
cur = con.cursor()
|
||||
admin = User(sys.argv[1], sys.argv[2], "admin")
|
||||
guest = User("guest", "guest", "guest")
|
||||
insert_person(admin)
|
||||
insert_person(guest)
|
||||
con.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print(f"Usage: {sys.argv[0]} <username> <password>")
|
||||
exit()
|
||||
main()
|
||||
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python3
|
||||
from burvesigner import BurveSigner
|
||||
from flask import Flask, make_response, render_template, request, flash
|
||||
from hashlib import sha256
|
||||
from time import time
|
||||
import base64
|
||||
import json
|
||||
import secrets
|
||||
import sqlite3
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config["SECRET_KEY"] = secrets.token_hex()
|
||||
db = "database.db"
|
||||
signer = BurveSigner()
|
||||
|
||||
|
||||
b64p = lambda x: x + b"=" * (-len(x) % 4)
|
||||
b64u = lambda x: x.rstrip(b"=")
|
||||
b64e = lambda x: b64u(base64.urlsafe_b64encode(x))
|
||||
b64d = lambda x: base64.urlsafe_b64decode(b64p(x))
|
||||
|
||||
|
||||
def generate_token(user, role):
|
||||
payload = b64e(json.dumps({
|
||||
"user": user,
|
||||
"role": role,
|
||||
"exp": int(time()) + 300
|
||||
}).encode())
|
||||
signature = signer.sign(payload)
|
||||
token = payload + b"." + signature
|
||||
return token.decode()
|
||||
|
||||
|
||||
def validate_token(token):
|
||||
assert token.count(".") == 1
|
||||
payload, signature = token.split(".")
|
||||
assert signer.verify(payload.encode(), signature.encode())
|
||||
payload = json.loads(b64d(payload.encode()).decode())
|
||||
assert payload.get("user") and payload.get("role") and payload.get("exp")
|
||||
user, role, exp = payload.get("user"), payload.get("role"), payload.get("exp")
|
||||
assert int(time()) < exp
|
||||
return [user, role, exp]
|
||||
|
||||
|
||||
def create_response_data(user, role):
|
||||
data = f"Welcome, {user}! "
|
||||
if role == "admin":
|
||||
try:
|
||||
data += open("/flag.txt").read()
|
||||
except:
|
||||
data += "Flag is missing, please contact probset"
|
||||
else:
|
||||
data += "Only admin can access the flag"
|
||||
return data
|
||||
|
||||
|
||||
def get_role(username, password):
|
||||
connection = sqlite3.connect(db)
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(
|
||||
"SELECT role FROM users WHERE username = ? AND password = ?",
|
||||
(username, sha256(b"gema" + password.encode() + b"steg").hexdigest()),
|
||||
)
|
||||
role = cursor.fetchone()
|
||||
connection.close()
|
||||
assert role
|
||||
return role[0]
|
||||
|
||||
|
||||
@app.route("/params", methods=["GET"])
|
||||
def params():
|
||||
return f"<pre>{json.dumps(signer.get_params(), indent=2)}</pre>"
|
||||
|
||||
|
||||
@app.route("/", methods=["POST", "GET"])
|
||||
def index():
|
||||
if request.method == "POST":
|
||||
username = request.form.get("username")
|
||||
password = request.form.get("password")
|
||||
try:
|
||||
assert 2 <= len(username) <= 32
|
||||
assert 2 <= len(password) <= 32
|
||||
role = get_role(username, password)
|
||||
token = generate_token(username, role)
|
||||
validate_token(token)
|
||||
response = make_response(render_template(
|
||||
"index.html",
|
||||
data=create_response_data(username, role)
|
||||
))
|
||||
response.set_cookie("token", token)
|
||||
return response
|
||||
except:
|
||||
flash("Invalid username and/or password")
|
||||
return render_template("index.html")
|
||||
else:
|
||||
token = request.cookies.get("token")
|
||||
if token:
|
||||
try:
|
||||
username, role, _ = validate_token(token)
|
||||
return render_template(
|
||||
"index.html",
|
||||
data=create_response_data(username, role)
|
||||
)
|
||||
except:
|
||||
flash("Invalid token")
|
||||
return render_template("index.html")
|
||||
else:
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=80, debug=False)
|
||||
@@ -0,0 +1,3 @@
|
||||
fastecdsa
|
||||
Flask
|
||||
pycryptodome
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
/usr/sbin/sshd -D &
|
||||
chmod +x ./main.py
|
||||
./main.py
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,8 @@
|
||||
function logout() {
|
||||
document.cookie = "token=;";
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
let flashItem = document.getElementById("flashes");
|
||||
flashItem.style.display = "none";
|
||||
}, 2000);
|
||||
@@ -0,0 +1,60 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 400px;
|
||||
margin: 5% auto;
|
||||
margin-bottom: 0;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
#flashes {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#flashes li {
|
||||
color: #ff6b6b;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>BurveSigner</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('static', filename='style.css') }}"
|
||||
/>
|
||||
<link
|
||||
rel="shortcut icon"
|
||||
href="{{ url_for('static', filename='favicon.ico') }}"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🅱️urveSigner</h1>
|
||||
{% if data %}
|
||||
<p>{{ data }}</p>
|
||||
<a onclick="logout()" href="/">Logout</a>
|
||||
{% else %}
|
||||
<form action="/" method="post">
|
||||
<input
|
||||
type="text"
|
||||
name="username"
|
||||
placeholder="Username"
|
||||
autofocus
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
placeholder="Password"
|
||||
required
|
||||
/>
|
||||
<input type="submit" value="Login" />
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% with messages = get_flashed_messages() %} {% if messages %}
|
||||
<ul id="flashes">
|
||||
{% for message in messages %}
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %} {% endwith %}
|
||||
</body>
|
||||
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user