How can I verify a plaintext password with a hash algorithm?
I have a question about salts. For example, there is a record in our database that looks like this:
Password: YUphoRF70vJEPAOjMmc/9n47hyQ=
Password Format: 1
Password Salt: Vx37L8ItQo3rJzx5gRCxTw==
I am trying to verify this password, but the method I am using isn't working.
This is the method:
public static string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Encoding.Unicode.GetBytes(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
And I pass it like this:
string encodedPasswd = Cryptography.EncodePassword(ClearTxtPassword, DbPasswordSalt);
What comes back does not look like the password in the database.
I am wondering if there is something else I should be doing to the salt? Is what is stored in the DB what I should be passing to the EncodePassword method or is there a step in between in which I should be decoding it prior to passing it as a parameter?
I am just not sure why I am getting a password mismatch. According to the web.config of the site I am working on, it is passwordFormat="Hashed" and the PasswordFormat column in the DB says "1" so I know it is SHA1.
Do you hav开发者_高级运维e any ideas why I am not getting the right match or how to get further along in figuring it out?(And yes, I have the right password.)
EDIT:
I have tried the following updated method:
public static string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Convert.FromBase64String(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
Against my current DB data and it still isn't matching up. For example, I am getting the following results:
passwordText = "administrator"
passwordformat: 1 / SHA1
passwordSaltInDb: "zVhahfmXj9MrOQySyPQ1Qw=="
passwordInDb = "YZ5xRJkNG9erGStAkWJA3hID9vE="
encodedPasswordResults = "DWZ6XRtVMy4l+XSUOKoX8usUOJI="
Is there any way that somebody could test on in their own environment to see why I am getting such different results?
If you're passing in the salt exactly as it's stored in the database then you're dealing with a Base-64 encoded string. To convert it to a byte[]
array you should use Convert.FromBase64String
rather than Unicode.GetBytes
. Something along these lines:
public static string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Convert.FromBase64String(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
By the way, although your question repeatedly mentions decrypting the password, it looks to me as if you're simply trying to validate a plaintext password against the stored hash. If that's the case then the above code should be fine.
If you really are trying to decrypt the stored hash then don't bother! The hash is not an encrypted version of the password, so decrypting it is impossible.
SHA1 isn't readily decryptable, which is one of the reasons it's used to store passwords. Why are you trying to decrypt the passwords?
精彩评论