【问题标题】:Converting HMAC-SHA1 from node.js to Java将 HMAC-SHA1 从 node.js 转换为 Java
【发布时间】:2016-09-28 14:08:05
【问题描述】:

我的任务是将一些现有的 node.js 代码转换为 Java。我想我的路很好,但我现在有点卡住了。方法的输出似乎不匹配。

我正在做的是基于查询字符串创建一个 SHA-1 签名。此查询字符串包含一些与查询相关的数据(与此问题无关)和一个 API 密钥。

重要

  • node.js 中的api_secret 字符串等同于Java 中的Config.API_SECRET
  • 示例查询字符串(在 node.js 和 Java 程序中是相等的):
    /events?festival=imaginate&pretty=1&size=100&from=0&key=SOME_KEY

实际代码

在nodejs中SHA-1 hmac的初始化如下:

const hmac = crypto.createHmac('sha1', api_secret);

SHA-1 mac在Java中初始化如下:

final SecretKeySpec secretKeySpec = new SecretKeySpec(Config.API_SECRET.getBytes("UTF-8"), "HmacSHA1");
final Mac hmac = Mac.getInstance("HmacSHA1");
hmac.init(secretKeySpec);

接下来,node.js程序更新hmac(query参数如上):

hmac.update(query, 'ascii');

我在 Java 中这样复制(query 参数等于 node.js 的 query 参数):

hmac.update(query.getBytes("US-ASCII"));

最后,字节字符串在 node.js 程序中被转换为 SHA-1 哈希:

const signature = hmac.digest('hex');

我找不到对 Java 的准确翻译,但这是我的尝试,我认为这样做的目的是相同的:

字节数组转十六进制函数

public static String byteArrayToHex(byte[] a) {
    StringBuilder sb = new StringBuilder(a.length * 2);
    for(byte b: a)
        sb.append(String.format("%02x", b & 0xff));
    return sb.toString();
}

实际使用情况

byte[] result = hmac.doFinal();
MessageDigest md = MessageDigest.getInstance("SHA-1");
String sha1Hash = byteArrayToHex(md.digest(result));

但是,这就是我感到困惑的地方。 node.js 程序返回这个哈希: 18cf4fce7bd6163c64d3b2ea8d935b0f16720fe3

但我的 Java 程序将此哈希作为输出: f65f8738cce89134dc73709e3353d94c83ccf1fb

我不知道我哪里出错了,我真的希望有人能解释一下。

【问题讨论】:

    标签: java node.js cryptography hmac hmacsha1


    【解决方案1】:

    我想通了!

    原来我做了一个不必要的步骤。

    这一行:

    byte[] result = mac.doFinal();
    

    已经包含签名哈希。我需要将该字节数组转换为十六进制字符串,而不是该字节数组的摘要。

    所以工作代码很简单:

    byte[] result = mac.doFinal();
    return byteArrayToHex(result);
    

    【讨论】:

      猜你喜欢
      • 2023-01-13
      • 2021-08-28
      • 1970-01-01
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-12
      • 1970-01-01
      相关资源
      最近更新 更多