EDIT:. For discussion in the comments, let me clarify that this will happen on the server side, for SSL. I do not intend to provide the client with a hashed password or hash scheme.
Suppose we have an existing asp.net identifier database with standard tables (aspnet_Users, aspnet_Roles, etc.). Based on my understanding, the password hashing algorithm uses sha256 and saves salt + (hashed password) as a base64 encoded string. EDIT: This assumption is incorrect, see answer below.
I would like to replicate the class function Microsoft.AspNet.Identity.Crypto ' VerifyHashedPassword with a version of JavaScript.
Let's say that the password is welcome1 , and its hash password is asp.net ADOEtXqGCnWCuuc5UOAVIvMVJWjANOA / LoVy0E4XCyUHIfJ7dfSY0Id + uJ20DTtG + A ==
So far, I have been able to reproduce parts of the method that get the salt and stored auxiliary key.
If the C # implementation does more or less:
var salt = new byte[SaltSize]; Buffer.BlockCopy(hashedPasswordBytes, 1, salt, 0, SaltSize); var storedSubkey = new byte[PBKDF2SubkeyLength]; Buffer.BlockCopy(hashedPasswordBytes, 1 + SaltSize, storedSubkey, 0, PBKDF2SubkeyLength);
I have JavaScript in JavaScript (not elegant by anything):
var hashedPwd = "ADOEtXqGCnWCuuc5UOAVIvMVJWjANOA/LoVy0E4XCyUHIfJ7dfSY0Id+uJ20DTtG+A=="; var hashedPasswordBytes = new Buffer(hashedPwd, 'base64'); var saltbytes = []; var storedSubKeyBytes = []; for(var i=1;i<hashedPasswordBytes.length;i++) { if(i > 0 && i <= 16) { saltbytes.push(hashedPasswordBytes[i]); } if(i > 0 && i >16) { storedSubKeyBytes.push(hashedPasswordBytes[i]); } }
Again, this is ugly, but after starting this fragment, the solibytes and storedSubKeyBytes coincide with the byte for the byte, which I see in the C # debugger for salt and storedSubkey.
Finally, in C #, an instance of Rfc2898DeriveBytes is used to generate a new subsection based on the salt and password provided, for example:
byte[] generatedSubkey; using (var deriveBytes = new Rfc2898DeriveBytes(password, salt, PBKDF2IterCount)) { generatedSubkey = deriveBytes.GetBytes(PBKDF2SubkeyLength); }
This is where I am stuck. I tried other solutions, such as this one , I used Google and Node CryptoJS and crypto libraries respectively, and my output never generates anything similar to the C # version.
(Example:
var output = crypto.pbkdf2Sync(new Buffer('welcome1', 'utf16le'), new Buffer(parsedSaltString), 1000, 32, 'sha256'); console.log(output.toString('base64'))
generates "LSJvaDM9u7pXRfIS7QDFnmBPvsaN2z7FMXURGHIuqdY =")
Many of the pointers I found on the Internet point to problems related to coding inconsistencies (NodeJS / UTF-8 compared to .NET / UTF-16LE), so I tried coding using the standard .NET coding format, but to no avail.
Or I could be completely wrong in what I assume these libraries do. But any pointers in the right direction would be greatly appreciated.