Подпись HMAC в java

Я пытаюсь преобразовать вызов POST узла js в Java. При этом я хочу изменить логику генерации подписи HMAC на метод java. Но подпись, похоже, не совпадает в узле js и в java. Я вставлю свой код node js и java ниже для справки:

const crypto = require('crypto');
const CONTENT_TYPE = 'Content-Type';
const APPLICATION_JSON_UTF8 = 'application/json; charset=utf-8';
const SIGNATURE = 'X-Hub-Signature';


const botConfig = {
    webhookURL: 'WEBHOOK_URL',
    secretKey: 'hP6pFhyqazD3vCuw5wjzGwicqF3nPq1H'
};


function buildSignatureHeader(buf, secret) {
    return 'sha256=' + buildSignature(buf, secret);
}

function buildSignature(buf, secret) {
    const hmac = crypto.createHmac('sha256', Buffer.from(secret, 'utf8'));
    hmac.update(buf);
    return hmac.digest('hex');
}

app.get('/', function (req, res) {
    const recvMessage =  {
                        "userId":"USERID",
                        "messagePayload": {
                            "type":"agent",
                            "text": "hi",
                            "channelName":"ENDPOINT"
                        },
                        "profile": {"firstName": 'SOMEUSER'}
                      };




console.log("Going to Call");
 const data = Buffer.from(JSON.stringify(recvMessage), 'utf8');
 const headers = {};
    headers[CONTENT_TYPE] = APPLICATION_JSON_UTF8;
    headers[SIGNATURE]    = buildSignatureHeader(data, botConfig.secretKey);
    var interactive = false;
    var oauth=false;
    console.log('signature:'+  buildSignatureHeader(JSON.stringify(recvMessage), botConfig.secretKey));

В Java мой код для генерации сертификата выглядит так:

public class HmacSha1Signature {
  /*  public HmacSha1Signature() {
        super();
    }
*/
  private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";

          private static String toHexString(byte[] bytes) {
                  Formatter formatter = new Formatter();

                  for (byte b : bytes) {
                          formatter.format("%02x", b);
                  }

                  return formatter.toString();
          }

          public static String calculateRFC2104HMAC(String data, String key)
                  throws SignatureException, NoSuchAlgorithmException, InvalidKeyException
          {
               SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
              Mac mac = Mac.getInstance("HmacSHA256");
              mac.init(signingKey);

              return toHexString(mac.doFinal(data.getBytes()));
          }

          public static void main(String[] args) throws Exception {

                  String data= "{\n" + 
                  "                        \"userId\":\"USERID\",\n" + 
                  "                        \"messagePayload\": {\n" + 
                  "                            \"type\":\"agent\",\n" + 
                  "                            \"text\": \"hi\",\n" + 
                  "                            \"channelName\":\"CHANNEL\"\n" + 
                  "                        },\n" + 
                  "                        \"profile\": {\"firstName\": 'SOMEUSER'}\n" + 
                  "                      }";
                  String hmac = calculateRFC2104HMAC(data, "hP6pFhyqazD3vCuw5wjzGwicqF3nPq1H");

                  System.out.println(hmac);

          }
} 

В NODE JS моя подпись выглядит так:

2176fd6b050b536f65ac146fb8471f1472098a7cc5e17bc61f85cf82e06e45d7

В то время как в java это:

2a899031182deda92c4cf97dd84c246ff65371acb9c41c04c360e1ab512e6038

Можете ли вы, ребята, помочь мне указать на ошибку, которую я здесь делаю. Почему подписи не совпадают?


person Bibin Mathew    schedule 30.11.2017    source источник
comment
Попробуйте изменить ввод на что-то более простое в обоих примерах, например. азбука. Я не уверен, что ваши входные строки идентичны.   -  person Henrik Aasted Sørensen    schedule 30.11.2017
comment
JSON.stringify() НЕ будет создавать строку, которую вы поместили в свой код Java.   -  person rustyx    schedule 06.07.2018


Ответы (1)


Для меня единственный способ вычислить подпись HMAC, которая работала в Java, это:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.codec.binary.Hex;

final String HMAC_SHA512 = "HmacSHA512";
final String CHARSET = "ISO-8859-1";
final String HMAC_KEY = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01...";

String hmacFootprint = null;
Mac mac = Mac.getInstance(HMAC_SHA512);
mac.init(new SecretKeySpec(DatatypeConverter.parseHexBinary(HMAC_KEY), mac.getAlgorithm()));
final byte[] macData = mac.doFinal(requestParameters.toString().getBytes());
byte[] hex = new Hex().encode(macData);
hmacFootprint = new String(hex, CHARSET).toUpperCase();

Надеюсь, поможет.

Благодаря этому ответу: генерация java hmac/sha512

person Paul    schedule 06.07.2018