0

Hello I'm trying to create Http Request to Api which needs data SHA512 encrypted. I've made same example in C# that works. In Android Java I can not reproduce hash and authenticate to WebApi. I think that the problem is that

mac.doFinal(byteData);

is creating byte array with negative values. In C# there are none negatives. Here is my code. Please tell me what am I doing wrong:

public static String calculateHMAC(String secret, String data) {
    byte[] byteSecret = secret.getBytes(StandardCharsets.UTF_8);
    byte[] byteData = data.getBytes(StandardCharsets.UTF_8);

    try {
        SecretKeySpec signingKey = new SecretKeySpec(byteSecret,    "HmacSHA512");
        Mac mac = Mac.getInstance("HmacSHA512");

        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(byteData); // -> Here Java makes rawMac with negative bytes
        return byteArrayToString(rawHmac);
    } catch (GeneralSecurityException e) {
        throw new IllegalArgumentException();
    }

}

private static String byteArrayToString(byte[] bytes) {

    StringBuilder sb = new StringBuilder();

    for(byte b : bytes){
        sb.append(Integer.toHexString(0xff & b));
    }
    return sb.toString();

}

Thanks in advance

silaros88
  • 65
  • 1
  • 7

2 Answers2

0

In Java there are no unsigned types so you cannot avoid negative values in binary data. It's not the problem.

One problem you have is in byteArrayToString(). toHexString() does not left-pad with zeros so values 0..15 don't output two chars but just one. I'd use something like String.format("%02x", b) instead. See also: How to convert a byte array to a hex string in Java?

laalto
  • 150,114
  • 66
  • 286
  • 303
  • Thank you for the answer. Ive tried this one too and it didnt help. Ive tried every solution on the Google. None of it work. C# creates hmac Sha512 that is correct and java doesnt. I dont know what to do now – silaros88 Jul 29 '18 at 13:27
0

Maybe I'm doing something wrong with my Http Post request. It needs HMAC SHA512 encryption. This is my test code:

public void postInfo() {
    String mApiKey = "$2y$10$6qyl9aYyT.3EV9uue5yup.eM6k1A9O98ZuZMYd0JBl5dbKRYNAF16";
    String mApiPin = "377eac53887e1cff2c7ff999";

    String params = "method=info&time=" + String.valueOf(System.currentTimeMillis() / 1000);

    final HttpClient httpclient = new DefaultHttpClient();
    final HttpPost httppost = new HttpPost(ApiEndPoint.ENDPOINT);

    try {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

        nameValuePairs.add(new BasicNameValuePair("method", "info"));
        nameValuePairs.add(new BasicNameValuePair("time", String.valueOf(System.currentTimeMillis() / 1000)));

        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        String hmac = HMAC.hash(mApiKey, params);

        httppost.addHeader("key", mApiKey);
        httppost.addHeader("hash", hmac);

        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    HttpResponse response = httpclient.execute(httppost);

                    HttpEntity entity = response.getEntity();

                    String content = EntityUtils.toString(entity); // Here it outputs that sign is incorrect

                    return;
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        });

        return;

    } catch (IOException e) {
        // TODO Auto-generated catch block
    }
}

public static String hash(String key, String msg) {
    byte[] returnVal = null;
    try {
        SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA512");
        Mac mac = Mac.getInstance("HmacSHA512");
        mac.init(signingKey);
        returnVal = mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
    }
    catch (Exception ex) {
        throw ex;
    }
    finally {
        return convertToHex(returnVal);
    }
}
silaros88
  • 65
  • 1
  • 7