You need to consider that a hash algorithm works on byte values, and you are using string values. This means that encoding will come in to play here, and from what I know PHP uses latin1 by default, while node.js uses utf-8.
crypto.createHash('md5').update(hashStr, 'ascii').digest('hex')
I'm not sure if ascii only handles 7-bit ascii or actual extended charsets like latin1, but it seems to be the only one supported directly in the update() method. If you need to control the extended charset, you should create a Buffer from the correct encoding, and use that as parameter to update() instead. The built in support in node.js is rather limited:
Buffer.isEncoding = function(encoding) { switch ((encoding + '').toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; default: return false; } };
And you should consider using some other tool to convert it. This thread (List of encodings that Node.js supports) suggests using iconv or iconv-lite.
Of course, the same applies to SHA1, but since you are using SHA1 on a hex representation of an MD5, it would never fall out of 7-bit ascii (where latin1 and utf-8 would produce the same byte sequence).
md5(salt, password)in your PHP andmd5(password, salt)in your JavaScript.