Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check ASP.NET password hash in node.js

First of all I read this Hashing a password using SHA256 and .NET/Node.js and it didn't help me.

I have to verify passwords hashes created in ASP.NET in node.js environment. I was told that passwords are generated using this algorithm: What is default hash algorithm that ASP.NET membership uses?.

I have example password hash and salt (first line is password and second line is salt):

"Password": "jj/rf7OxXM263rPgvLan4M6Is7o=",
"PasswordSalt": "/Eju9rmaJp03e3+z1v5s+A==",

I know that hash algorithm is SHA1 and I know that above hash is generated for input test123. However I can't reproduce hashing algorithm to get same hash for this input. What I tried:

Password = "jj/rf7OxXM263rPgvLan4M6Is7o="
PasswordSalt = "/Eju9rmaJp03e3+z1v5s+A=="
crypto = require("crypto")
sha1 = crypto.createHash("sha1")
PasswordSalt = new Buffer(PasswordSalt, 'base64').toString('utf8')
sha1.update(PasswordSalt+"test123", "utf8")
result = sha1.digest("base64")
console.log(Password)
console.log(result)

Result is:

jj/rf7OxXM263rPgvLan4M6Is7o=
xIjxRod4+HVYzlHZ9xomGGGY6d8=

I was able to get working C# algorithm:

using System.IO;
using System;
using System.Text;
using System.Security.Cryptography;

class Program
{

    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);
    }

    static void Main()
    {
        string pass = "test123";
        string salt = "/Eju9rmaJp03e3+z1v5s+A==";
        string hash = Program.EncodePassword(pass,salt);
        Console.WriteLine(hash);
        // outputs jj/rf7OxXM263rPgvLan4M6Is7o=
    }
}

So now it is just a matter of porting this algorithm to node.js. The problem is that c# somehow magically operates on bytes and I don't know how to do it in node. Consider following code (it does not use any salt - it just creates base64 sha1 from password:

crypto = require("crypto")
pass = 'test123'
sha1 = crypto.createHash("sha1")
buf = new Buffer( pass, 'utf8')
sha1.update(buf)
result = sha1.digest("base64")
console.log(result)
// outputs cojt0Pw//L6ToM8G41aOKFIWh7w=

And in c#

 using System.Text;
 using System.Security.Cryptography;
 string pass = "test123";
 byte[] bytes = Encoding.Unicode.GetBytes(pass);
 HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
 byte[] inArray = algorithm.ComputeHash(bytes);
 string hash = Convert.ToBase64String(inArray);
 Console.WriteLine(hash);
 // outputs Oc/baVMs/zM28IqDqsQlJPQc1uk=

I need code in node.js that will return same value as code in c#. Any ideas?

like image 832
user606521 Avatar asked Sep 09 '14 13:09

user606521


People also ask

What is password hashing in node JS?

Password hashing means passing a plain text password through a hashing algorithm to generate a unique value. Some examples of hashing algorithms are bcrypt, scrypt, and SHA. The downside of hashing is that it is predictable. Every time you pass the same input to a hashing algorithm, it will generate the same output.

How do I verify my bcrypt password?

To hash a password use bcrypt. hash(plainTextPassword, salt, callback) which returns a promise if no callback is passed. To verify plain text password with hashed password use bcrypt. compare(plainTextPassword, hashedPassword, callback) which also returns a promise if no callback is passed.

What is bcrypt in node JS?

The bcrypt hashing function allows us to build a password security platform that scales with computation power and always hashes every password with a salt.

What is bcrypt hash?

BCrypt Algorithm is used to hash and salt passwords securely. BCrypt permits building a password security stage that can advance nearby hardware innovation to guard against dangers or threats in the long run, like attackers having the computing power to guess passwords twice as quickly.


2 Answers

I finally found the right answer here: https://gist.github.com/PalmerEk/1191651 (with little change from 'ucs2' to 'utf16le'):

function dotnet_membership_password_hash(pass, salt)
{
  var bytes = new Buffer(pass || '', 'utf16le');
  var src = new Buffer(salt || '', 'base64');
  var dst = new Buffer(src.length + bytes.length);
  src.copy(dst, 0, 0, src.length);
  bytes.copy(dst, src.length, 0, bytes.length);

  return crypto.createHash('sha1').update(dst).digest('base64');
}
like image 169
user606521 Avatar answered Sep 27 '22 23:09

user606521


there is a nodejs module which does all the magic for you. No function on stackoverflow worked in my case, but this module works:

https://www.npmjs.com/package/aspnet-identity-pw

  var passwordHasher = require('aspnet-identity-pw');

  var hashedPassword = passwordHasher.hashPassword('SomePassword');

  var isValid = passwordHasher.validatePassword('SomePassword', hashedPassword);
like image 43
EscapeNetscape Avatar answered Sep 27 '22 23:09

EscapeNetscape