0

I am trying to migrate a sha-512 computation from java to node JS and I can't seem to get the same results...

Java code (which looks standard from what I saw online):

public class Test
{
    private static String get_SecurePassword(String passwordToHash, String salt, String algo) throws NoSuchAlgorithmException
    {
        String generatedPassword = null;

        MessageDigest md = MessageDigest.getInstance(algo);
        md.update(salt.getBytes());
        byte[] bytes = md.digest(passwordToHash.getBytes());
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i< bytes.length; i++) {
            sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }

        generatedPassword = sb.toString();

        return generatedPassword;
    }

    public static void main(String[] args) throws NoSuchAlgorithmException
    {
        String res = get_SecurePassword("test", "test", "SHA-512");

        System.out.println(res);
    }
}

Output:

125d6d03b32c84d492747f79cf0bf6e179d287f341384eb5d6d3197525ad6be8e6df0116032935698f99a09e265073d1d6c32c274591bf1d0a20ad67cba921bc

NodeJS:

const crypto = require('crypto');

function getSecurePassword(password, salt, algo) {
    const algoFormatted = algo.toLowerCase().replace('-', '');
    const hash = crypto.createHmac(algoFormatted, salt);
    hash.update(password);

    const res = hash.digest('hex');

    return res;
}

console.log(getSecurePassword('test', 'test', 'SHA-512'));

Output:

9ba1f63365a6caf66e46348f43cdef956015bea997adeb06e69007ee3ff517df10fc5eb860da3d43b82c2a040c931119d2dfc6d08e253742293a868cc2d82015

What am I doing wrong?

Note: I am using Java 8 and Node 10.13

Tomer Amir
  • 1,515
  • 4
  • 27
  • 54
  • Your NodeJS result is the correct one according to [Freeformatter](https://www.freeformatter.com/hmac-generator.html#ad-output). – RaminS Jan 29 '19 at 18:59
  • 1
    You're calling `getBytes()` without specifying a character encoding. Depending on your data and the default platform encoding on your system, that can change what you're passing for the salt and the plaintext. – David Conrad Jan 29 '19 at 19:01
  • Ohhh... So the Java code is not a standard `sha-512`? if so, how can I replicate it? @Gendarme – Tomer Amir Jan 29 '19 at 19:02
  • Thanks @DavidConrad, I tryied adding encoding to the Java code, but this didn't help (both codes were ran on the same system) – Tomer Amir Jan 29 '19 at 19:02

3 Answers3

6

In Node you're using HMAC-SHA-512, but in Java you're just using SHA-512 and concatenating the key and the plaintext. That is not how HMAC works. You need to use HMAC-SHA-512 in Java as well:

import static java.nio.charset.StandardCharsets.*;

import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Test {
    private static String getSecurePassword(String password, String salt, String algo)
            throws NoSuchAlgorithmException, InvalidKeyException {
        SecretKeySpec secretKeySpec = new SecretKeySpec(salt.getBytes(UTF_8), algo);
        Mac mac = Mac.getInstance(algo);
        mac.init(secretKeySpec);
        byte[] bytes = mac.doFinal(password.getBytes(UTF_8));

        return new BigInteger(1, bytes).toString(16);
    }

    public static void main(String[] args)
            throws NoSuchAlgorithmException, InvalidKeyException {
        System.out.println(getSecurePassword("test", "test", "HmacSHA512"));
    }
}

Output:

9ba1f63365a6caf66e46348f43cdef956015bea997adeb06e69007ee3ff517df10fc5eb860da3d43b82c2a040c931119d2dfc6d08e253742293a868cc2d82015
David Conrad
  • 15,432
  • 2
  • 42
  • 54
2

If someone is looking to the Node JS fix I made thanks to @DavidConrad, here it is:

const crypto = require('crypto');

function getSecurePassword(password, salt, algo) {
    const algoFormatted = algo.toLowerCase().replace('-', '');
    const hash = crypto.createHash(algoFormatted);
    hash.update(salt + password);

    return hash.digest('hex');
}

console.log(getSecurePassword('test', 'test', 'SHA-512'));

Output:

125d6d03b32c84d492747f79cf0bf6e179d287f341384eb5d6d3197525ad6be8e6df0116032935698f99a09e265073d1d6c32c274591bf1d0a20ad67cba921bc
Tomer Amir
  • 1,515
  • 4
  • 27
  • 54
0

For NodeJS, you can append the key with data to get Java equivalent hash.

require('crypto').createHash(algo).update(data + key).digest()
Satya
  • 429
  • 3
  • 8