vmangos
This commit is contained in:
@@ -4,64 +4,37 @@ namespace App\Services;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
|
||||
/** The site's legacy AzerothCore SRP format, independent of the game ticket. */
|
||||
class AzerothCoreSrpService
|
||||
{
|
||||
private const string MODULUS_HEX = '894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7';
|
||||
|
||||
private const int GENERATOR = 7;
|
||||
|
||||
private const int BYTE_LENGTH = 32;
|
||||
|
||||
public function normalizeUsername(string $username): string
|
||||
{
|
||||
return strtoupper(trim($username));
|
||||
}
|
||||
|
||||
public function normalizeEmail(string $email): string
|
||||
{
|
||||
return strtoupper(trim($email));
|
||||
}
|
||||
|
||||
public function normalizePassword(string $password): string
|
||||
{
|
||||
return strtoupper($password);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{0: string, 1: string}
|
||||
*/
|
||||
public function makeRegistrationData(string $username, string $password): array
|
||||
{
|
||||
$saltHex = strtoupper(bin2hex(random_bytes(self::BYTE_LENGTH)));
|
||||
$saltHex = strtoupper(bin2hex(random_bytes(32)));
|
||||
|
||||
return [$saltHex, $this->makeVerifierHex($username, $password, $saltHex)];
|
||||
}
|
||||
|
||||
public function makeVerifierHex(string $username, string $password, string $saltHex): string
|
||||
{
|
||||
$normalizedUsername = $this->normalizeUsername($username);
|
||||
$normalizedPassword = $this->normalizePassword($password);
|
||||
$salt = hex2bin($saltHex);
|
||||
|
||||
if ($salt === false) {
|
||||
throw new \InvalidArgumentException('Invalid salt hex provided.');
|
||||
if ($salt === false || strlen($salt) !== 32) {
|
||||
throw new \InvalidArgumentException('Invalid site credential salt.');
|
||||
}
|
||||
|
||||
$innerDigest = hash('sha1', sprintf('%s:%s', $normalizedUsername, $normalizedPassword), true);
|
||||
$xDigest = hash('sha1', $salt.$innerDigest, true);
|
||||
$modulus = BigInteger::fromBase(self::MODULUS_HEX, 16);
|
||||
$exponent = BigInteger::fromBytes(strrev($xDigest), false);
|
||||
$verifier = BigInteger::of(self::GENERATOR)->modPow($exponent, $modulus);
|
||||
$verifierBytes = strrev(str_pad($verifier->toBytes(false), self::BYTE_LENGTH, "\0", STR_PAD_LEFT));
|
||||
$digest = hash('sha1', strtoupper(trim($username)).':'.strtoupper($password), true);
|
||||
$x = hash('sha1', $salt.$digest, true);
|
||||
$verifier = BigInteger::of(7)->modPow(
|
||||
BigInteger::fromBytes(strrev($x), false),
|
||||
BigInteger::fromBase(self::MODULUS_HEX, 16),
|
||||
);
|
||||
|
||||
return strtoupper(bin2hex($verifierBytes));
|
||||
return strtoupper(bin2hex(strrev(str_pad($verifier->toBytes(false), 32, "\0", STR_PAD_LEFT))));
|
||||
}
|
||||
|
||||
public function credentialsMatch(string $username, string $password, string $saltHex, string $verifierHex): bool
|
||||
{
|
||||
return hash_equals(
|
||||
strtoupper($verifierHex),
|
||||
$this->makeVerifierHex($username, $password, $saltHex),
|
||||
);
|
||||
return hash_equals(strtoupper($verifierHex), $this->makeVerifierHex($username, $password, $saltHex));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user