second commit
parent
8442713311
commit
bc19dd67e9
|
@ -0,0 +1,41 @@
|
|||
import hashlib
|
||||
import os
|
||||
from flask import Flask, request, render_template, redirect
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Global storage for the current challenge
|
||||
current_challenge = {}
|
||||
|
||||
# Redirect root URL to get-challenge
|
||||
@app.route('/', methods=['GET'])
|
||||
def index():
|
||||
return redirect('/get-challenge') # Redirect to the challenge page
|
||||
|
||||
# Generate a nonce and difficulty for the client
|
||||
@app.route('/get-challenge', methods=['GET'])
|
||||
def get_challenge():
|
||||
global current_challenge
|
||||
nonce = os.urandom(16).hex() # Generate a random 16-byte nonce
|
||||
difficulty = 4 # Set the difficulty (number of leading zeros)
|
||||
current_challenge = {'nonce': nonce, 'difficulty': difficulty}
|
||||
return render_template('challenge.html', nonce=nonce, difficulty=difficulty)
|
||||
|
||||
# Verify the solution provided by the client
|
||||
@app.route('/verify', methods=['POST'])
|
||||
def verify_solution():
|
||||
solution = request.form['solution']
|
||||
nonce = current_challenge['nonce']
|
||||
difficulty = current_challenge['difficulty']
|
||||
|
||||
# Recompute the hash with the client's solution
|
||||
hash_result = hashlib.sha256((nonce + solution).encode()).hexdigest()
|
||||
|
||||
# Check if the hash has the required number of leading zeros
|
||||
if hash_result.startswith('0' * difficulty):
|
||||
return render_template('result.html', status="Success! Solution is correct.")
|
||||
else:
|
||||
return render_template('result.html', status="Failed. Incorrect solution.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=6969)
|
|
@ -0,0 +1,11 @@
|
|||
* Serving Flask app 'app'
|
||||
* Debug mode: off
|
||||
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
|
||||
* Running on all addresses (0.0.0.0)
|
||||
* Running on http://127.0.0.1:6969
|
||||
* Running on http://87.120.112.23:6969
|
||||
Press CTRL+C to quit
|
||||
172.58.127.76 - - [22/Oct/2024 15:40:16] "GET / HTTP/1.1" 200 -
|
||||
172.58.127.76 - - [22/Oct/2024 15:40:16] "GET /static/main.js HTTP/1.1" 200 -
|
||||
172.58.127.76 - - [22/Oct/2024 15:40:17] "GET /favicon.ico HTTP/1.1" 404 -
|
||||
172.58.127.76 - - [22/Oct/2024 15:40:18] "GET /get-challenge HTTP/1.1" 200 -
|
|
@ -0,0 +1,16 @@
|
|||
import hashlib
|
||||
|
||||
# Get user inputs for nonce and difficulty
|
||||
nonce = input("Enter the nonce: ")
|
||||
difficulty = int(input("Enter the difficulty (number of leading zeros): "))
|
||||
|
||||
def sha256(message):
|
||||
return hashlib.sha256(message.encode()).hexdigest()
|
||||
|
||||
solution = 0
|
||||
while True:
|
||||
hash_result = sha256(nonce + str(solution))
|
||||
if hash_result.startswith('0' * difficulty):
|
||||
print("Solution found:", solution)
|
||||
break
|
||||
solution += 1
|
|
@ -0,0 +1,47 @@
|
|||
async function sha256(message) {
|
||||
const msgBuffer = new TextEncoder().encode(message);
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
return hashHex;
|
||||
}
|
||||
|
||||
async function startPoW() {
|
||||
document.getElementById('status').innerText = "Starting PoW...";
|
||||
|
||||
// Fetch challenge from the server
|
||||
const response = await fetch('/get-challenge');
|
||||
const challenge = await response.json();
|
||||
const { nonce, difficulty } = challenge;
|
||||
|
||||
let solution = 0;
|
||||
let hash = '';
|
||||
|
||||
// Brute-force to find a solution
|
||||
while (true) {
|
||||
hash = await sha256(nonce + solution);
|
||||
if (hash.startsWith('0'.repeat(difficulty))) {
|
||||
break;
|
||||
}
|
||||
solution++;
|
||||
}
|
||||
|
||||
document.getElementById('status').innerText = `Solution found: ${solution} (Hash: ${hash})`;
|
||||
|
||||
// Send the solution back to the server for verification
|
||||
const verifyResponse = await fetch('/verify', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ nonce, solution: solution.toString(), difficulty })
|
||||
});
|
||||
|
||||
if (verifyResponse.status === 200) {
|
||||
document.getElementById('status').innerText += " - Verified!";
|
||||
} else {
|
||||
document.getElementById('status').innerText += " - Verification failed!";
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('start-pow').addEventListener('click', startPoW);
|
|
@ -0,0 +1,77 @@
|
|||
body {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
background-color: #1e1e1e; /* Dark background for a circuit board feel */
|
||||
color: #c9c9c9; /* Light text color */
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: #2e2e2e; /* Darker box background */
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
||||
max-width: 600px; /* Limit width for better appearance */
|
||||
margin: auto; /* Center the container */
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
color: #4CAF50; /* Green text for headers */
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: 2px solid #4CAF50; /* Underline for h1 */
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
width: 100%; /* Full width for input */
|
||||
border: 1px solid #4CAF50; /* Green border */
|
||||
border-radius: 4px;
|
||||
background-color: #333; /* Darker input field */
|
||||
color: #c9c9c9; /* Light text color */
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 15px;
|
||||
background-color: #4CAF50; /* Green button */
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s; /* Smooth hover transition */
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #45a049; /* Darker green on hover */
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
margin-top: 20px;
|
||||
text-decoration: none;
|
||||
color: #4CAF50; /* Green for links */
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline; /* Underline links on hover */
|
||||
}
|
||||
|
||||
.code-box {
|
||||
background-color: #2e2e2e; /* Dark background for code boxes */
|
||||
border: 1px solid #4CAF50; /* Green border for code boxes */
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
overflow-x: auto; /* Allow horizontal scrolling */
|
||||
font-family: 'Courier New', Courier, monospace; /* Monospace font for code */
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Proof of Work Challenge</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Proof of Work Challenge</h1>
|
||||
<p><strong>Nonce:</strong> {{ nonce }}</p>
|
||||
<p><strong>Difficulty:</strong> {{ difficulty }}</p>
|
||||
|
||||
<h2>Instructions</h2>
|
||||
<p>To solve the Proof of Work challenge, run the following Python script locally with the provided nonce:</p>
|
||||
<div class="code-box">
|
||||
<pre>
|
||||
import hashlib
|
||||
|
||||
nonce = "{{ nonce }}"
|
||||
difficulty = {{ difficulty }}
|
||||
|
||||
def sha256(message):
|
||||
return hashlib.sha256(message.encode()).hexdigest()
|
||||
|
||||
solution = 0
|
||||
while True:
|
||||
hash_result = sha256(nonce + str(solution))
|
||||
if hash_result.startswith('0' * difficulty):
|
||||
print("Solution found:", solution)
|
||||
break
|
||||
solution += 1
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Once you've found the solution, enter it below:</p>
|
||||
|
||||
<form action="/verify" method="post">
|
||||
<label for="solution">Solution:</label>
|
||||
<input type="text" id="solution" name="solution" required>
|
||||
<button type="submit">Verify</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Verification Result</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Verification Result</h1>
|
||||
<p>{{ status }}</p>
|
||||
|
||||
<a href="/get-challenge">Try Another Challenge</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue