Files
wow-registrace/includes/Srp6.php
T
vojta 2b9a673912 Initial commit: AzerothCore registration site
PHP registration page for AzerothCore with SRP6 salt/verifier generation,
Cloudflare Turnstile + honeypot + rate limiting anti-spam, and a WoW-themed
landing page with client setup instructions.
2026-08-05 11:41:24 +02:00

66 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
/**
* SRP6 salt/verifier generation compatible with AzerothCore's authserver
* (same constants and algorithm as TrinityCore/MaNGOS, mandated by the WoW
* client itself, so this is stable across expansions/versions).
*
* Algorithm (matches AzerothCore's SRP6::MakeRegistrationData /
* ac-nodejs-srp6's computeVerifier):
* s = random 32 bytes (salt)
* h1 = SHA1(UPPER(username) + ":" + UPPER(password))
* x = SHA1(s . h1) interpreted as a LITTLE-endian integer
* v = g^x mod N (verifier)
* Both s and v are stored little-endian, zero-padded to 32 bytes, in the
* `account`.`salt` / `account`.`verifier` BINARY(32) columns.
*/
final class Srp6
{
// Fixed 256-bit prime and generator used by the WoW client's SRP6 implementation.
private const N_HEX = '894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7';
private const G = 7;
private const KEY_LENGTH = 32;
/**
* @return array{salt: string, verifier: string} raw 32-byte binary strings
*/
public static function makeRegistrationData(string $username, string $password): array
{
if (!extension_loaded('gmp')) {
throw new RuntimeException('Chybí PHP rozšíření GMP (php-gmp), nutné pro výpočet SRP6 verifieru.');
}
$username = strtoupper($username);
$password = strtoupper($password);
$salt = random_bytes(self::KEY_LENGTH);
$h1 = sha1($username . ':' . $password, true);
$xHash = sha1($salt . $h1, true);
$x = gmp_import($xHash, 1, GMP_LSW_FIRST | GMP_LITTLE_ENDIAN);
$n = gmp_init(self::N_HEX, 16);
$g = gmp_init(self::G, 10);
$v = gmp_powm($g, $x, $n);
$verifier = self::gmpToLittleEndianBytes($v, self::KEY_LENGTH);
return [
'salt' => $salt,
'verifier' => $verifier,
];
}
private static function gmpToLittleEndianBytes(\GMP $value, int $length): string
{
$bytes = gmp_export($value, 1, GMP_LSW_FIRST | GMP_LITTLE_ENDIAN);
if (strlen($bytes) > $length) {
throw new RuntimeException('SRP6 verifier přesáhl očekávanou délku.');
}
return str_pad($bytes, $length, "\0", STR_PAD_RIGHT);
}
}