The default Implementation and Application of IPasswordHasher encryption for Microsoft. Identity in Asp.net,
I believe that I have understood the MS Identity Authentication System and must know the role of UserManager. He is the dispatcher in the system and defines a set of user behaviors to help us manage user information and role information, process passwords. But its implementation is in UserStore, we can implement what we define for us, such as IUserStore, IUserPasswordStore, IRoleStore, and so on. we can customize our user information, data structures, and data storage based on a set of user behaviors. Then, concerning the Hasher of Password, MS still provides a complete behavior definition, which is also scheduled by UserManager. For example
UserManager.PasswordHasher.HashPassword(password)
PasswordHasher is defined in the UserManager interface as follows:
I was not interested in its default implementation. For the login authentication purpose of multiple independent applications, an independent user authentication project is required as the authentication service, which only produces tokens, after successful authentication, the Authorization of the user's HTTP Request Header takes the token to access various resources on the application server.
For this reason, there is a problem with password authentication for multiple applications:
For example, application A uses IPasswordHasher to customize the encryption method-MD5 + salt, and application B uses the default PasswordHasher of Identity. The following code is obtained through decompilation:
Therefore, in order to be compatible with different encryption methods of multiple applications, I had to decompile the source code and obtain the default encryption method. Based on Different Application names, I decided to encrypt or decrypt the password, or compare the password entered by the database and the user in some way. First, the default PasswordHasher of MS is implemented.
// Decompiled with JetBrains decompiler// Type: Microsoft.AspNet.Identity.Crypto// Assembly: Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35// MVID: E3A10FFD-023A-4BC3-AD53-32D145ABF1C9// Assembly location: C:\Sport\NewProject\V2.0\Api\Fantasy.Sport\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dllusing System;using System.Runtime.CompilerServices;using System.Security.Cryptography;namespace Microsoft.AspNet.Identity{ internal static class Crypto { private const int PBKDF2IterCount = 1000; private const int PBKDF2SubkeyLength = 32; private const int SaltSize = 16; public static string HashPassword(string password) { if (password == null) throw new ArgumentNullException("password"); byte[] salt; byte[] bytes; using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, 16, 1000)) { salt = rfc2898DeriveBytes.Salt; bytes = rfc2898DeriveBytes.GetBytes(32); } byte[] inArray = new byte[49]; Buffer.BlockCopy((Array) salt, 0, (Array) inArray, 1, 16); Buffer.BlockCopy((Array) bytes, 0, (Array) inArray, 17, 32); return Convert.ToBase64String(inArray); } public static bool VerifyHashedPassword(string hashedPassword, string password) { if (hashedPassword == null) return false; if (password == null) throw new ArgumentNullException("password"); byte[] numArray = Convert.FromBase64String(hashedPassword); if (numArray.Length != 49 || (int) numArray[0] != 0) return false; byte[] salt = new byte[16]; Buffer.BlockCopy((Array) numArray, 1, (Array) salt, 0, 16); byte[] a = new byte[32]; Buffer.BlockCopy((Array) numArray, 17, (Array) a, 0, 32); byte[] bytes; using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, 1000)) bytes = rfc2898DeriveBytes.GetBytes(32); return Crypto.ByteArraysEqual(a, bytes); } [MethodImpl(MethodImplOptions.NoOptimization)] private static bool ByteArraysEqual(byte[] a, byte[] b) { if (object.ReferenceEquals((object) a, (object) b)) return true; if (a == null || b == null || a.Length != b.Length) return false; bool flag = true; for (int index = 0; index < a.Length; ++index) flag &= (int) a[index] == (int) b[index]; return flag; } }}
Someone may ask how to apply the source code. The following is a brief introduction to this problem.
At the beginning, I naively thought that it was not an encryption. I don't have to read it carefully. I just want to use it?
When registering a user and changing the password, the above HashPassword method is used to encrypt the password. Then, in the new custom PasswordHasher, when I compare the user login password for application B, is it okay to encrypt user input directly through HashPassword? Therefore, the self-defined VerifyHashedPassword (Verify translated as verification) method compares the Pwd in the database with the result processed by hasher. The result is that different encryption results are generated for each same string, which is different from the md5 + salt. So I thought of its default VerifyHashedPassword method.
So the last thing you should talk about is that you can use the encryption method of Microsoft Identity (the Hasher above) directly. When comparing the user input and the database's hash Storage results, use its VerifyHashedPassword () method. This encryption algorithm can be used even if Identity authentication is not used.
The above is all the content of this article. I hope this article will help you in your study or work. I also hope to provide more support to the customer's home!