Ryanhub - file viewer
filename: html/api/services/register/submit.php
branch: main
back to repo
<?php
require_once __DIR__ . '/../../lib/response.php';
require_once __DIR__ . '/../../lib/db.php';

// read body
$body = json_decode(file_get_contents('php://input'), true);
if (!is_array($body)) {
    json(['error' => 'invalid_json'], 400);
}

$challenge = $body['challenge'] ?? null;
$nonce = $body['nonce'] ?? null;
$hash = $body['hash'] ?? null;

if (!is_string($challenge) || !is_string($nonce) || !is_string($hash)) {
    json(['error' => 'missing_fields'], 400);
}

// find db entry for challenge
$q = $pdo->prepare('SELECT difficulty, expires_at FROM pow_challenges WHERE challenge = ?');
$q->execute([$challenge]);
$row = $q->fetch();
if (!$row) {
    json(['error' => 'unknown_challenge'], 400);
}

if (time() > (int)$row['expires_at']) {
    json(['error' => 'challenge_expired'], 400);
}

$difficulty = (int)$row['difficulty'];

// verify hash
$expected = hash('sha256', $challenge . $nonce);
if (!hash_equals($expected, $hash)) {
    json(['error' => 'invalid_hash'], 400);
}
$prefix = str_repeat('0', max(0, $difficulty));
if (strpos($hash, $prefix) !== 0) {
    json(['error' => 'insufficient_difficulty'], 400);
}

// generate api key
$apiKey = bin2hex(random_bytes(32));
$apiKeyHash = hash('sha256', $apiKey);

// store key
$q = $pdo->prepare('INSERT INTO api_keys (key_hash, revoked) VALUES (?, 0)');
$q->execute([$apiKeyHash]);

// delete challenge
$q = $pdo->prepare('DELETE FROM pow_challenges WHERE challenge = ?');
$q->execute([$challenge]);

// return 200 + newly registered api key
json(['api_key' => $apiKey]);