Initial commit.
This commit is contained in:
commit
0a9434be1b
18 changed files with 1860 additions and 0 deletions
5
server/python-flask/README.md
Normal file
5
server/python-flask/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
NOJSCAP Python server example with Flask.
|
||||
|
||||
# Running
|
||||
|
||||
python3 server.py
|
136
server/python-flask/server.py
Normal file
136
server/python-flask/server.py
Normal file
|
@ -0,0 +1,136 @@
|
|||
from flask import Flask, request
|
||||
import hashlib, os, time
|
||||
|
||||
app = Flask(__name__)
|
||||
DIFFICULTY = 20
|
||||
challenge_store = {}
|
||||
|
||||
def generate_challenge():
|
||||
return os.urandom(12).hex()
|
||||
|
||||
def check_difficulty(hash_bytes, bits):
|
||||
i = 0
|
||||
while bits > 0:
|
||||
byte = hash_bytes[i]
|
||||
if bits >= 8:
|
||||
if byte != 0: return False
|
||||
bits -= 8
|
||||
else:
|
||||
if byte & (0xFF << (8 - bits)) != 0: return False
|
||||
bits = 0
|
||||
i += 1
|
||||
return True
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
def index():
|
||||
challenge = generate_challenge()
|
||||
challenge_store[challenge] = time.time()
|
||||
return f'''
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>NOJSCAP demo</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
body {{
|
||||
padding: 20px;
|
||||
margin-bottom: 300px;
|
||||
background: #cacaca;
|
||||
color: black;
|
||||
}}
|
||||
code {{
|
||||
white-space: break-spaces;
|
||||
background: black;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
display: block;
|
||||
max-width: 500px;
|
||||
}}
|
||||
.h {{
|
||||
font-size: 21px;
|
||||
font-weight: bolder;
|
||||
width: 100%;
|
||||
float: left;
|
||||
}}
|
||||
button {{
|
||||
background: #006ed0;
|
||||
color: white;
|
||||
border: 1px solid #006ed0;
|
||||
padding: 10px 20px;
|
||||
margin-top: 10px;
|
||||
}}
|
||||
input {{
|
||||
background: black;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
display: block;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
border: 0px solid transparent;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>NOJSCAP demo</h1>
|
||||
<p><a href="https://git.libroot.org/libroot/NOJSCAP/" target="_blank">https://git.libroot.org/libroot/NOJSCAP/</a></p><p><br></p>
|
||||
<p>If you don't already have the <b><em>NOJSCAP</em></b> client:</p>
|
||||
<code>$ git clone https://git.libroot.org/libroot/NOJSCAP/
|
||||
$ cd NOJSCAP/client/</code>
|
||||
<p><br></p>
|
||||
<p>
|
||||
<code>$ python3 pow_client.py {challenge} {DIFFICULTY}</code>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Go:</strong>
|
||||
</p>
|
||||
<p>
|
||||
<code>$ go run pow_client.go {challenge} {DIFFICULTY}</code>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Node.js:</strong>
|
||||
</p>
|
||||
<p>
|
||||
<code>$ node pow_client.js {challenge} {DIFFICULTY}</code>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Rust:</strong>
|
||||
</p>
|
||||
<p>
|
||||
<code>$ rustc pow_client.rs -o pow_client_rs
|
||||
$ pow_client_rs {challenge} {DIFFICULTY}
|
||||
</code>
|
||||
<small>Requires Rust and sha2 crate if using the Cargo version.</small>
|
||||
</p>
|
||||
<p>
|
||||
<strong>C:</strong>
|
||||
</p>
|
||||
<p>
|
||||
<code>$ gcc -O2 -o pow_client pow_client.c -lssl -lcrypto
|
||||
$ ./pow_client {challenge} {DIFFICULTY}
|
||||
</code>
|
||||
<small>Required: GCC or any C compiler. OpenSSL development libraries (libssl-dev on Debian-based systems)</small>
|
||||
</p>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="challenge" value="{challenge}">
|
||||
<label class="h">Nonce: <input name="nonce"></label>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
@app.route('/', methods=['POST'])
|
||||
def submit():
|
||||
challenge = request.form.get("challenge")
|
||||
nonce = request.form.get("nonce")
|
||||
if challenge not in challenge_store: return "Invalid challenge"
|
||||
challenge_store.pop(challenge)
|
||||
combined = (challenge + nonce).encode()
|
||||
h = hashlib.sha256(combined).digest()
|
||||
return "<p>Success! Valid nonce.</p><a href='/'>Try again</a>" if check_difficulty(h, DIFFICULTY) else "<p>Invalid nonce.</p><a href='/'>Try again</a>"
|
||||
|
||||
app.run(port=3000)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue