initial login logic
This commit is contained in:
83
altcha_utils.py
Normal file
83
altcha_utils.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import hashlib
|
||||
import hmac
|
||||
import secrets
|
||||
import base64
|
||||
import json
|
||||
import time
|
||||
|
||||
|
||||
class AltchaChallenge:
|
||||
"""Self-hosted Altcha challenge generator and verifier."""
|
||||
|
||||
def __init__(self, hmac_key=None):
|
||||
self.hmac_key = hmac_key or secrets.token_hex(32)
|
||||
|
||||
def create_challenge(self, max_number=100000):
|
||||
"""Generate a new Altcha challenge."""
|
||||
salt = secrets.token_hex(12)
|
||||
secret_number = secrets.randbelow(max_number) + 1
|
||||
|
||||
# Create the challenge string that needs to be solved
|
||||
challenge_data = f"{salt}{secret_number}"
|
||||
challenge = hashlib.sha256(challenge_data.encode()).hexdigest()
|
||||
|
||||
# Create signature for verification
|
||||
signature = hmac.new(
|
||||
self.hmac_key.encode(),
|
||||
challenge.encode(),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
return {
|
||||
"algorithm": "SHA-256",
|
||||
"challenge": challenge,
|
||||
"maxnumber": max_number,
|
||||
"salt": salt,
|
||||
"signature": signature
|
||||
}
|
||||
|
||||
def verify_solution(self, payload):
|
||||
"""Verify an Altcha solution payload."""
|
||||
try:
|
||||
# Decode base64 payload
|
||||
decoded = base64.b64decode(payload).decode('utf-8')
|
||||
data = json.loads(decoded)
|
||||
|
||||
algorithm = data.get('algorithm', '')
|
||||
challenge = data.get('challenge', '')
|
||||
number = data.get('number', 0)
|
||||
salt = data.get('salt', '')
|
||||
signature = data.get('signature', '')
|
||||
|
||||
# Verify algorithm
|
||||
if algorithm.upper() != 'SHA-256':
|
||||
return False
|
||||
|
||||
# Verify signature
|
||||
expected_signature = hmac.new(
|
||||
self.hmac_key.encode(),
|
||||
challenge.encode(),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
if not hmac.compare_digest(signature, expected_signature):
|
||||
return False
|
||||
|
||||
# Verify the solution
|
||||
challenge_data = f"{salt}{number}"
|
||||
computed_challenge = hashlib.sha256(challenge_data.encode()).hexdigest()
|
||||
|
||||
return hmac.compare_digest(computed_challenge, challenge)
|
||||
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
_altcha_instances = {}
|
||||
|
||||
|
||||
def get_altcha(hmac_key):
|
||||
"""Get or create an Altcha instance for the given HMAC key."""
|
||||
if hmac_key not in _altcha_instances:
|
||||
_altcha_instances[hmac_key] = AltchaChallenge(hmac_key)
|
||||
return _altcha_instances[hmac_key]
|
||||
Reference in New Issue
Block a user