Answered by:
why does a hash give two different results with the same input?

Question
-
User297437924 posted
I tried the following code in a test page with a label. Despite giving the same input to the hasher, I get two different results. Why is that?
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load Dim password As String = "xD?cJ287mYx?JH" Dim sph As PasswordHasher = New PasswordHasher() Dim PasswordHash2 As String PasswordHash2 = sph.HashPassword(password) Dim password2 As String = "xD?cJ287mYx?JH" Dim sph2 As PasswordHasher = New PasswordHasher() Dim PasswordHash22 As String PasswordHash22 = sph2.HashPassword(password2) Me.uclabel.Text = PasswordHash2 & " versus " & PasswordHash22 End Sub
Friday, August 10, 2018 5:21 PM
Answers
-
User753101303 posted
Hi,
See https://en.wikipedia.org/wiki/Salt_(cryptography)
In short the idea is to add a random password to the user defined password to massively slowing down attacks (and it won't change anything if all users are using the same password). If this is a.NET implementation you could likely have a look at the source code to better get how it works.
You should find a method to which you provide a clear text password and the hash value and that tells if they match.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, August 10, 2018 6:52 PM -
User283571144 posted
Hi RateFor,
As far as I know, the haspassword use Key Derivation Function with random salt to produce the hash.
The salt is included as part of the output of the KDF. Thus, each time you "hash" the same password you will get different hashes.
To verify the hash the output is split back to the salt and the rest, and the KDF is run again on the password with the specified salt.
If the result matches to the rest of the initial output the hash is verified.
Hash function code:
public static string HashPassword(string password) { byte[] salt; byte[] buffer2; if (password == null) { throw new ArgumentNullException("password"); } using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8)) { salt = bytes.Salt; buffer2 = bytes.GetBytes(0x20); } byte[] dst = new byte[0x31]; Buffer.BlockCopy(salt, 0, dst, 1, 0x10); Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20); return Convert.ToBase64String(dst); }
Verify:
public static bool VerifyHashedPassword(string hashedPassword, string password) { byte[] buffer4; if (hashedPassword == null) { return false; } if (password == null) { throw new ArgumentNullException("password"); } byte[] src = Convert.FromBase64String(hashedPassword); if ((src.Length != 0x31) || (src[0] != 0)) { return false; } byte[] dst = new byte[0x10]; Buffer.BlockCopy(src, 1, dst, 0, 0x10); byte[] buffer3 = new byte[0x20]; Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20); using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, dst, 0x3e8)) { buffer4 = bytes.GetBytes(0x20); } return ByteArraysEqual(buffer3, buffer4); }
Best Regards,
Brando
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, August 13, 2018 7:06 AM
All replies
-
User753101303 posted
Hi,
See https://en.wikipedia.org/wiki/Salt_(cryptography)
In short the idea is to add a random password to the user defined password to massively slowing down attacks (and it won't change anything if all users are using the same password). If this is a.NET implementation you could likely have a look at the source code to better get how it works.
You should find a method to which you provide a clear text password and the hash value and that tells if they match.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, August 10, 2018 6:52 PM -
User283571144 posted
Hi RateFor,
As far as I know, the haspassword use Key Derivation Function with random salt to produce the hash.
The salt is included as part of the output of the KDF. Thus, each time you "hash" the same password you will get different hashes.
To verify the hash the output is split back to the salt and the rest, and the KDF is run again on the password with the specified salt.
If the result matches to the rest of the initial output the hash is verified.
Hash function code:
public static string HashPassword(string password) { byte[] salt; byte[] buffer2; if (password == null) { throw new ArgumentNullException("password"); } using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8)) { salt = bytes.Salt; buffer2 = bytes.GetBytes(0x20); } byte[] dst = new byte[0x31]; Buffer.BlockCopy(salt, 0, dst, 1, 0x10); Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20); return Convert.ToBase64String(dst); }
Verify:
public static bool VerifyHashedPassword(string hashedPassword, string password) { byte[] buffer4; if (hashedPassword == null) { return false; } if (password == null) { throw new ArgumentNullException("password"); } byte[] src = Convert.FromBase64String(hashedPassword); if ((src.Length != 0x31) || (src[0] != 0)) { return false; } byte[] dst = new byte[0x10]; Buffer.BlockCopy(src, 1, dst, 0, 0x10); byte[] buffer3 = new byte[0x20]; Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20); using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, dst, 0x3e8)) { buffer4 = bytes.GetBytes(0x20); } return ByteArraysEqual(buffer3, buffer4); }
Best Regards,
Brando
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, August 13, 2018 7:06 AM