2016-09-28 60 views
1

我的任務是將一些現有的node.js代碼轉換爲Java。我認爲我很順利,但我現在有點困難。這些方法的輸出似乎不匹配。將HMAC-SHA1從node.js轉換爲Java

我在做什麼是基於查詢字符串創建一個SHA-1簽名。該查詢字符串包含一些與查詢相關的數據(與此問題無關)和API密鑰。

重要

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

實際代碼

的SHA-1 HMAC作爲在如下的NodeJS初始化:

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

我想不通,我錯在哪裏,我真的希望有人能擺脫光在這。

回答

0

我想通了!

原來我正在做一個不必要的步驟。

這條線:

byte[] result = mac.doFinal(); 

已經包含在簽名中的散列。我需要將該字節數組轉換爲十六進制字符串,而不是該字節數組的摘要。

所以工作代碼很乾脆:

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