-
-
Save Rochet2/3bb0adaf6f3e9a9fbc78ba5ce9a43e09 to your computer and use it in GitHub Desktop.
using System; | |
using System.Security.Cryptography; | |
using System.Text; | |
using System.Numerics; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Globalization; | |
public static class SRP6CryptoHasher { | |
private static readonly RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider(); | |
// algorithm constants | |
private static readonly BigInteger g = 7; | |
private static readonly BigInteger N = new BigInteger("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7".ToByteArray(true), true); | |
public static(byte[] Salt, byte[] Verifier) GetSRP6RegistrationData(string username, string password) { | |
// generate a random salt | |
byte[] salt = new byte[32]; | |
rngCsp.GetBytes(salt); | |
// calculate verifier using this salt | |
byte[] verifier = CalculateSRP6Verifier(username, password, salt); | |
// done - this is what you put in the account table! | |
return (salt, verifier); | |
} | |
public static byte[] CalculateSRP6Verifier(string username, string password, byte[] salt_bytes) { | |
SHA1 sha1 = SHA1.Create(); | |
// calculate first hash | |
byte[] login_bytes = Encoding.UTF8.GetBytes((username + ':' + password).ToUpper()); | |
byte[] h1_bytes = sha1.ComputeHash(login_bytes); | |
// calculate second hash | |
byte[] h2_bytes = sha1.ComputeHash(salt_bytes.Concat(h1_bytes).ToArray()); | |
// convert to integer (little-endian) | |
BigInteger h2 = new BigInteger(h2_bytes, true); | |
// g^h2 mod N | |
BigInteger verifier = BigInteger.ModPow(g, h2, N); | |
// convert back to a byte array (little-endian) | |
byte[] verifier_bytes = verifier.ToByteArray(); | |
// pad to 32 bytes, remember that zeros go on the end in little-endian! | |
byte[] verifier_bytes_padded = new byte[Math.Max(32, verifier_bytes.Length)]; | |
Buffer.BlockCopy(verifier_bytes, 0, verifier_bytes_padded, 0, verifier_bytes.Length); | |
// done! | |
return verifier_bytes_padded; | |
} | |
public static 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); | |
// compare it against the stored verifier | |
return verifier.SequenceEqual(checkVerifier); | |
} | |
public static void Main(string[] args) { | |
// Example code | |
// When creating account | |
// store the returned data to database | |
// Never store the actual password | |
var data = GetSRP6RegistrationData("username", "password"); | |
// When logging in | |
// verify login | |
bool validLoginInfo = VerifySRP6Login("username", "password", data.Salt, data.Verifier); | |
Console.WriteLine("Username and password match the stored data: " + validLoginInfo); | |
// When program should close | |
rngCsp.Dispose(); | |
} | |
} |
Also, for further reference, this was coded based on the php examples here: TrinityCore/TrinityCore#25157
i can try now.
string query2 = "INSERT INTO account (username, salt, verifier) VALUES (@username,@binarydata1,@binaryData2)";
AuthConn.Open();
byte[] salt = new byte[32];
rngCsp.GetBytes(salt);
// calculate verifier using this salt
byte[] verifier = CalculateSRP6Verifier("TELLMEWHY", "TELLMEWHY", salt);
MySqlCommand cmd = new MySqlCommand(query2, AuthConn);
cmd.Parameters.Add(new MySqlParameter("@username", MySqlDbType.VarChar) { Value = UserName.ToUpper() });
cmd.Parameters.Add(new MySqlParameter("@binarydata1", MySqlDbType.Binary) { Value = salt });
cmd.Parameters.Add(new MySqlParameter("@binaryData2", MySqlDbType.Binary) { Value = verifier });
cmd.ExecuteNonQuery();//here insert db successful,
// my test here
var data = GetSRP6RegistrationData("TELLMEWHY", "TELLMEWHY");
// When logging in
// verify login
bool validLoginInfo = VerifySRP6Login("TELLMEWHY", "TELLMEWHY", data.salt, data.verifier);
ConsoleHelper.WriteErr(true, "Username and password match the stored data: " + validLoginInfo);
// validLoginInfo value is :True , but can't login TC
AuthConn.Close();
Based on this commit: TrinityCore/TrinityCore@623202d
there might be new variants of the algorithm that need to be implemented or the implementation may need tweaking to work since a year ago.
What is the srp_version set to for the login info in battlenet_accounts? If it is 2, try setting it to 1.
thx, i'll try
You may also be interested in this implementation:
https://github.com/CypherCore/CypherCore/blob/master/Source/Framework/Cryptography/SRP6.cs
I tried all of the above and failed. test on tc3.3.5. .gave up.
Can't login latest TC,,invalid password!
Result result = GetSRP6RegistrationData(UserName, Pass);
...
cmd.Parameters.Add(new MySqlParameter("@username", MySqlDbType.VarChar) { Value = UserName.ToUpper() });
cmd.Parameters.Add(new MySqlParameter("@binarydata1", MySqlDbType.Binary) { Value = result.salt });
cmd.Parameters.Add(new MySqlParameter("@binaryData2", MySqlDbType.Binary) { Value = result.verifier });
cmd.ExecuteNonQuery();