'Method not allowed']); exit; } $input = json_decode(file_get_contents('php://input'), true); $challenge = $input['challenge'] ?? null; $difficulty = $input['difficulty'] ?? POW_DIFFICULTY; $nonce = $input['nonce'] ?? null; $signature = $input['signature'] ?? null; $timestamp = $input['timestamp'] ?? null; if (!$challenge || $nonce === null || !$signature || !$timestamp) { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Missing fields']); exit; } $now = (int)(microtime(true) * 1000); if ($now - $timestamp > POW_TTL_SECONDS * 1000) { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Challenge expired']); exit; } $expected = hash_hmac('sha256', "$challenge:$timestamp:$difficulty", POW_SECRET); if (!hash_equals($expected, $signature)) { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Invalid signature']); exit; } $hash = hash('sha256', $challenge . $nonce); $prefix = str_repeat('0', $difficulty); if (strpos($hash, $prefix) !== 0) { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Invalid proof']); exit; } echo json_encode(['ok' => true]);