TrinityCore deprecated the old sha_pass_hash column on the auth table, in favour of the much safer SRP6 method. However, I am unable to properly calculate the verifier in C#/dotnet NOR in PHP using the example provided here. I've looked at examples but it doesn't seem to be working the way that the TrinityCore developers suggest. Does anyone know about SRP6 that might be able to figure out what's wrong in the code? I've also looked at this example but it uses a hardcoded salt? If someone can show me what's wrong in the PHP I might be able to figure out what's wrong with the .NET
The code I tried looks closest to the first example, but I flip my arrays around to be little-endian.
public byte[] CalculateVerifier(string username, string password, byte[] salt)
{
if (BitConverter.IsLittleEndian)
{
return BigInteger.ModPow(
g,
new BigInteger(Hash(salt, Hash(Encoding.UTF8.GetBytes($"{username.ToUpper()}:{password.ToUpper()}")))),
N
).ToByteArray();
}
else
{
return BigInteger.ModPow(
g,
new BigInteger(Hash(salt, Hash(Encoding.UTF8.GetBytes($"{username.ToUpper()}:{password.ToUpper()}")).Reverse().ToArray())),
N
).ToByteArray();
}
}
public bool VerifySRP6Login(string username, string password, byte[] salt, byte[] verifier)
{
// re-calculate the verifier using the provided username + password and the stored salt
byte[] checkVerifier = CalculateSRP6Verifier(username, password, salt);
Console.WriteLine($"{Encoding.ASCII.GetString(verifier)} {verifier.Length} bytes\n{Encoding.ASCII.GetString(checkVerifier)} {checkVerifier.Length} bytes");
Console.WriteLine($"{new BigInteger(verifier)}\n{new BigInteger(checkVerifier)}");
// compare it against the stored verifier
return verifier.SequenceEqual(checkVerifier);
}
public byte[] Hash(byte[] componentOne, byte[] componentTwo)
{
if (componentOne == null) throw new ArgumentNullException(nameof(componentOne));
if (componentTwo == null) throw new ArgumentNullException(nameof(componentTwo));
//WoW expects non-secure SHA1 hashing. SRP6 is deprecated too. We need to do it anyway
using (SHA1 shaProvider = SHA1.Create())
{
//See Jackpoz's Combine function
return shaProvider.ComputeHash(componentOne.Concat(componentTwo).ToArray());
}
}
public byte[] Hash(byte[] bytes)
{
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
//WoW expects non-secure SHA1 hashing. SRP6 is deprecated too. We need to do it anyway
using (SHA1 shaProvider = SHA1.Create())
{
return shaProvider.ComputeHash(bytes);
}
}
The answer was found in this solution, apparently I wasn't properly making my BigInteger, because the data was an unsigned int and I was treating it as signed.