I've tried to calculate a hashed password.
The mechanism is decribed here:
First step, to get the challenge from an HTTP-Request with follwing result:
<?xml version="1.0" encoding="utf-8"?> <SessionInfo> <SID>0000000000000000</SID> <Challenge>2$60000$f56cbe583d35a155cfbdf24c8d6bfa45$6000$99a2a02c9bd6989e52307a6e83bab646</Challenge> <BlockTime>0</BlockTime> <Rights></Rights> <Users> <User last="1">root</User> </Users> </SessionInfo> The challenge is build as following data:
<type>$<ter1>$<salt1>$<ter2>$<salt2> <iter1> = 60000 <salt1> = f56cbe583d35a155cfbdf24c8d6bfa45 <iter2> = 6000 <salt2> = 99a2a02c9bd6989e52307a6e83bab646 The password will hashed as following (source from code in PDF):
# Hash twice, once with static salt... hash1 = hashlib.pbkdf2_hmac("sha256", password.encode(), salt1, iter1) # Once with dynamic salt. hash2 = hashlib.pbkdf2_hmac("sha256", hash1, salt2, iter2) And here is my C# Code to try the hashing:
private void CreateChallenge(String challenge, LoginData data) { // PBKDF2 (ab FRITZ!OS 7.24) if(challenge.Contains("$")) { String[] parts = challenge.Split('$'); String type = parts[0]; // 2 int iter1 = int.Parse(parts[1]); // 600000 byte[] salt1 = Encoding.UTF8.GetBytes(parts[2]); // HEX int iter2 = int.Parse(parts[3]); // 600000 byte[] salt2 = Encoding.UTF8.GetBytes(parts[4]); // HEX System.Diagnostics.Debug.Print("Salt 1: " + parts[2] + " ~> " + iter1); System.Diagnostics.Debug.Print("Salt 2: " + parts[4] + " ~> " + iter2); // Calculate byte[] hash1 = HMAC(Encoding.UTF8.GetBytes(data.Password), salt1, iter1); System.Diagnostics.Debug.Print("Hashed PW: " + BitConverter.ToString(hash1).Replace("-", "")); byte[] hash2 = HMAC(hash1, salt2, iter2); System.Diagnostics.Debug.Print("Hashed Request: " + BitConverter.ToString(hash2).Replace("-", "")); this.CallSignin(parts[4] + "$" + BitConverter.ToString(hash2).Replace("-", "").ToLower(), data); // MD5-Fallback } else { this.CallSignin(challenge + "-" + MD5(challenge + "-" + data.Password), data); } } private byte[] HMAC(byte[] input, byte[] salt, int iterations) { using (var pbkdf2 = new Rfc2898DeriveBytes(input, salt, iterations, HashAlgorithmName.SHA256)) { return Encoding.UTF8.GetBytes(pbkdf2.ToString()); //return pbkdf2.GetBytes(length); } } private String MD5(String input) { MD5 hasher = System.Security.Cryptography.MD5.Create(); byte[] data = hasher.ComputeHash(Encoding.UTF8.GetBytes(input)); StringBuilder output = new StringBuilder(); for(int index = 0; index < data.Length; index++) { output.Append(data[index].ToString("x2")); } return output.ToString().ToLower(); } And here is a sample Call:
CreateChallenge("2$60000$f56cbe583d35a155cfbdf24c8d6bfa45$6000$99a2a02c9bd6989e52307a6e83bab646", new LoginData() { Username = "root", Password = "123Test" }); But curiously i've get follwing output:
Salt 1: f56cbe583d35a155cfbdf24c8d6bfa45 ~> 60000 Salt 2: 99a2a02c9bd6989e52307a6e83bab646 ~> 6000 Hashed PW: 53797374656D2E53656375726974792E43727970746F6772617068792E526663323839384465726976654279746573 Hashed Request: 53797374656D2E53656375726974792E43727970746F6772617068792E526663323839384465726976654279746573 Result: 99a2a02c9bd6989e52307a6e83bab646$53797374656d2e53656375726974792e43727970746f6772617068792e526663323839384465726976654279746573 Question
WHY is the Hashed PW complete the same as Hashed Request?
Both using other values..
Can anyone help me?
Change the HMAC Method and tried to use other mechanics for Rfc2898DeriveBytes