Last active
October 13, 2024 06:55
-
-
Save sphinxid/610be4302400a3c8dda95421ae0b256c to your computer and use it in GitHub Desktop.
This code simulates a client-server interaction using a Proof-of-Work (PoW) system. In such systems, the client must solve a computational challenge set by the server in order to have its request processed. This particular code makes use of SHA3-256 hashing and requires the hash of a unique challenge and a nonce to have a specific number of lead…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hashlib | |
import hmac | |
import time | |
import secrets | |
import random | |
# Secret Key for HMAC (In a real-world scenario, this should be stored securely) | |
SECRET_KEY = b"SayaOrangPalingGantengSedunia" # Change this in production | |
# Difficulty (number of leading zeroes required in the hash) | |
DIFFICULTY = 5 | |
# Maximum time difference (in seconds) | |
TIME_DIFF = 300 | |
# Nonce Range | |
NONCE_RANGE = 10**10 | |
def generate_challenge(): | |
return hashlib.sha3_256(str(secrets.randbits(64)).encode()).hexdigest() | |
def server_set_challenge(): | |
challenge = generate_challenge() | |
unique_str = secrets.token_hex(16) | |
timestamp = int(time.time()) | |
challenge_with_unique_str = challenge + unique_str | |
digest = hmac.new(SECRET_KEY, f"{challenge_with_unique_str}{timestamp}".encode(), hashlib.sha3_256).hexdigest() | |
print(f"Server: The challenge is '{challenge}', find a nonce such that the SHA3-256 hash of the challenge + unique string + nonce has at least {DIFFICULTY} leading zeroes.") | |
return challenge_with_unique_str, timestamp, digest | |
def client_solve_challenge(challenge, server_timestamp): | |
print("Client: Solving challenge...") | |
start_time = time.time() | |
nonce = random.randint(0, NONCE_RANGE) | |
while True: | |
data = f"{challenge}{server_timestamp}{nonce}" | |
hash_result = hashlib.sha3_256(data.encode()).hexdigest() | |
if hash_result.startswith("0" * DIFFICULTY): | |
end_time = time.time() | |
print(f"Hash result: {hash_result}") | |
print(f"Client timestamp: {start_time}") | |
print(f"Server timestamp: {server_timestamp}") | |
print(f"Client: Challenge solved in {end_time - start_time:.2f} seconds, nonce: {nonce}") | |
return nonce, int(start_time) | |
nonce = (nonce + 1) % NONCE_RANGE | |
def server_verify_solution(challenge, nonce, client_timestamp, server_timestamp, original_digest): | |
current_timestamp = int(time.time()) | |
# Verify the original challenge hasn't been tampered with | |
calculated_digest = hmac.new(SECRET_KEY, f"{challenge}{server_timestamp}".encode(), hashlib.sha3_256).hexdigest() | |
if calculated_digest != original_digest: | |
print("Server: Challenge has been tampered with.") | |
return False | |
# Check if the solution is within the time limit | |
if current_timestamp - client_timestamp > TIME_DIFF: | |
print("Server: Solution is too old, request rejected.") | |
return False | |
# Verify the solution | |
data = f"{challenge}{server_timestamp}{nonce}" | |
hash_result = hashlib.sha3_256(data.encode()).hexdigest() | |
if hash_result.startswith("0" * DIFFICULTY): | |
print("Server: Solution is correct, processing request...") | |
time.sleep(1) # Simulate request processing | |
print("Server: Request processed") | |
return True | |
else: | |
print("Server: Incorrect solution") | |
return False | |
def simulate_api_request(): | |
challenge, server_timestamp, digest = server_set_challenge() | |
nonce, client_timestamp = client_solve_challenge(challenge, server_timestamp) | |
server_verify_solution(challenge, nonce, client_timestamp, server_timestamp, digest) | |
def main(): | |
simulate_api_request() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
$ python3.10 pow04.py
Server: The challenge is '45834afa64a3eb05a15e01c11feeee05f6dc1db3bae17d7dc15eb55b947de79e', you need to find a nonce such that the SHA3-256 hash of the challenge + unique string, and nonce together has at least 5 leading zeroes.
Client: Solving challenge...
hash result -> 000005faf2176f73d9ff080893587183ef6cf6ed1ef307f930d547dcf5221dc8
client timestamp -> 1686118872.015199
server timestamp -> 1686118872
Client: Challenge solved in 1.4372360706329346 seconds, the nonce is 6410631986
Server: Solution is correct, processing request...
Server: Request processed