Last active
December 27, 2024 05:53
-
-
Save Rochet2/3bb0adaf6f3e9a9fbc78ba5ce9a43e09 to your computer and use it in GitHub Desktop.
SRP6 for TC in C#/csharp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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();