51 lines
1.6 KiB
PHP
51 lines
1.6 KiB
PHP
<?php
|
||
/**
|
||
* SRP6 (WoW/MaNGOS) – génération de v et s corrects.
|
||
* Points clés :
|
||
* - USERNAME & PASSWORD en MAJUSCULES
|
||
* - x = SHA1( salt || SHA1(USER:PASS) )
|
||
* - N = 0x894B...E9BB7 (256-bit), g = 7
|
||
* - Endianness : on évite gmp_import et on passe par hex pour ne pas se tromper
|
||
* - Hex MAJUSCULE + padding à la longueur de N
|
||
*/
|
||
final class SRP6
|
||
{
|
||
// N et g utilisés par WoW (256-bit)
|
||
private const N_HEX = '894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7';
|
||
private const G_HEX = '07';
|
||
|
||
public static function createVerifierAndSalt(string $username, string $password): array
|
||
{
|
||
$U = strtoupper($username);
|
||
$P = strtoupper($password);
|
||
|
||
// 32 octets de sel (=> 64 hex)
|
||
$saltBin = random_bytes(32);
|
||
|
||
// h1 = SHA1(U:P)
|
||
$h1 = sha1($U . ':' . $P, true);
|
||
|
||
// h2 = SHA1(salt || h1)
|
||
$h2 = sha1($saltBin . $h1, true);
|
||
|
||
// x = int( h2 ) (interprété comme un entier non signé big-endian)
|
||
// -> on passe par l'hex pour éviter les soucis d'endianness
|
||
$x = gmp_init(bin2hex($h2), 16);
|
||
|
||
$N = gmp_init(self::N_HEX, 16);
|
||
$g = gmp_init(self::G_HEX, 16);
|
||
|
||
// v = g^x mod N
|
||
$v = gmp_powm($g, $x, $N);
|
||
|
||
// Longueur hex attendue = longueur de N en hex (ici 64 chars)
|
||
$nLen = strlen(self::N_HEX);
|
||
|
||
// Hex MAJUSCULE + padding
|
||
$vHex = strtoupper(str_pad(gmp_strval($v, 16), $nLen, '0', STR_PAD_LEFT));
|
||
$sHex = strtoupper(str_pad(bin2hex($saltBin), 64, '0', STR_PAD_LEFT)); // 32 bytes => 64 hex
|
||
|
||
return ['v' => $vHex, 's' => $sHex];
|
||
}
|
||
}
|