I've been strugling for a while now by trying to complete next goal : I have a "Reset password" page that supposed to send new password to the server. I would like to hash it with salt, so I could save it in DB eventually. On Server side I have next methods that creates password hash :
public static String makeHash(String password, String salt) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes("UTF-8"));
byte byteData[] = md.digest(makeHash(salt.toLowerCase()));
return Base64.getEncoder().encodeToString(byteData);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
log.error("Unable to make hash for pass. No hashing.", e);
}
return password;
}
private static byte[] makeHash(String val) throws NoSuchAlgorithmException, UnsupportedEncodingException {
return MessageDigest.getInstance("SHA-256").digest(val.getBytes("UTF-8"));
}
I tried several Javascript libraries - crypto, crypto-js, SJCL , but couldn't manage to create same password as Java methods generates. For example, last working try out was :
var crypto = require('crypto');
crypto.pbkdf2('123', 'test@gmail.com', 1000, 60, 'sha256', function(err, key) {
if (err)
throw err;
console.log(key.toString('Base64')); // 'c5e478d...1469e50'
});
And it generated me this hash - Qr2lzotlRWj7BeJeFooMRj64auMPTb3PRhwLmfNcl4DCVAlFFibgOqZiyExZNO5i/icAUYoMjy73jSTd
, while Java gives me - /pyQf3JCj5XoczfsYJ4LUb+y0DONGMl/AFzLiBTo8LA=
.
I cannot change backend, since it running already for some time, so I was hoping that maybe someone could help me out with this.
You have to use the same algorithm on both sides. In Java you're using simply SHA-256 and in node you're using PBKDF2 with SHA-256.
Node.js' crypto module provides the createHash(algorithm)
function. Where you can specify SHA-256 directly. PBKDF2 is an algorithm that only uses different hashing functions under the hood.
If you want hash passwords, then it is much safer to use PBKDF2 with a lot of iterations (> 86,000) and a random salt that you store alongside the password hash.
Java has support for PBKDF2 in its standard library.
If you really want to use SHA-256 directly and I strongly advise against it, you can use the following code:
var crypto = require('crypto');
var key = "123";
var salt = "test@gmail.com";
key = crypto.createHash('sha256')
.update(key, "utf8")
.update(makeHash(salt))
.digest("base64");
console.log(key);
function makeHash(val) {
return crypto.createHash('sha256').update(val, "utf8").digest();
}
Output:
/pyQf3JCj5XoczfsYJ4LUb+y0DONGMl/AFzLiBTo8LA=
Note that Hash.digest()
takes an optional output encoding and not additional data.