module hunt.database.driver.mysql.impl.util.Native41Authenticator; import hunt.text.Charset; import hunt.Exceptions; import std.digest.sha; /** * */ class Native41Authenticator { /** * Native authentication method 'mysql_native_password' * Calculate method: SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) ) * * @param password password value * @param charset charset of password * @param salt 20 byte random challenge from server * @return scrambled password */ static byte[] encode(string password, Charset charset, byte[] salt) { scope SHA1Digest messageDigest = new SHA1Digest(); // SHA1(password) ubyte[] passwordHash1 = messageDigest.digest(password); messageDigest.reset(); // SHA1(SHA1(password)) ubyte[] passwordHash2 = messageDigest.digest(passwordHash1); messageDigest.reset(); // SHA1("20-bytes random data from server" <concat> SHA1(SHA1(password)) messageDigest.put(cast(ubyte[])salt); messageDigest.put(passwordHash2); ubyte[] passwordHash3 = messageDigest.finish(); // result = passwordHash1 XOR passwordHash3 for (int i = 0; i < cast(int)passwordHash1.length; i++) { passwordHash1[i] = cast(byte) (passwordHash1[i] ^ passwordHash3[i]); } return cast(byte[])passwordHash1; } }