在Java中的HMAC SHA1签名

问题描述:

我想与TransUnion Web服务接口,我需要提供一个HMAC-SHA1签名来访问它。在Java中的HMAC SHA1签名

这个例子是环联文档中:
安全输入的SampleIntegrationOwner2008‐11‐18T19:14:40.293ZxBy/2CLudnBJOxOtDhDRnsDYq9HTuDVr2uCs3FMzoxXEA/Od9tOuwSC70+mIfpjeG68ZGm/PrxFf/s/CzwxF4Q== 创建的/UhwvT/kY9HxiXaOjpIc/BarBkc=输出。

鉴于数据和密钥,我无法在Java中获得相同的结果。我已经尝试了几种在线计算器,并且他们都没有返回这个结果。他们的文档中的示例是不正确的,还是我没有正确处理这些字符串?

这里是我目前正与代码:

public static String calcShaHash (String data, String key) { 
    String HMAC_SHA1_ALGORITHM = "HmacSHA1";  
    String result = null; 

    try {   
     Key signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM); 
     Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); 
     mac.init(signingKey); 
     byte[] rawHmac = mac.doFinal(data.getBytes()); 
     result = Base64.encodeBase64String(rawHmac);  
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    }  

    return result; 
} 

这里是我的单元测试代码:

@Test 
public void testCalcShaHash() { 
    String data = "SampleIntegrationOwner2008-11-18T19:14:40.293Z"; 
    String key = "xBy/2CLudnBJOxOtDhDRnsDYq9HTuDVr2uCs3FMzoxXEA/Od9tOuwSC70+mIfpjeG68ZGm/PrxFf/s/CzwxF4Q=="; 
    String result = Utils.calcShaHash(data, key); 
    assertEquals(result, "/UhwvT/kY9HxiXaOjpIc/BarBkc="); 

} 
+1

从文档的更大的摘录可能会有所帮助。我注意到的一件事是连字符不是正常的连字符。如果您复制并粘贴它们,它们不在ASCII字符集中。我可以肯定地说哈希长度显示正确。 –

+0

@John Watts - 你对破折号的评论是正确的。我复制并粘贴来自Word文档的文本。破折号不是标准的ASCII字符。通过使用正常破折号,结果是正确的,无需解码密钥。请添加您的评论作为答案。 – Shane

一件事我注意到的是,连字符是不正常的连字符。如果您复制并粘贴它们,它们不在ASCII字符集中。我可以肯定地说哈希长度显示正确。有趣的是,即使在输入正确的连字符后,我也无法让你的代码产生正确的答案。但是不管。它解决了这个问题。好哇!

+0

@Shane你可以在这里复制你最新的SSCE吗?我复制了你的原始代码,用适当的连字符更新它,但它仍然失败。我认为还有另一个区别,我们还没有确定我想保留后代。 –

这看起来像一个Base64编码的关键。所以我认为你需要对它做一个base64解码,然后把它传递给HMAC。像这样的东西(只是为了说明我没有测试过,任何错误都为读者的练习):

public String getHmacMD5(String privateKey, String input) throws Exception{ 
    String algorithm = "HmacSHA1"; 
    byte[] keyBytes = Base64.decode(privateKey); 
    Key key = new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm); 
    Mac mac = Mac.getInstance(algorithm); 
    mac.init(key); 
    return Base64.encode(mac.doFinal(input.getBytes())); 
} 
+0

我试过了,但还是没有得到正确的答案。见上面的代码示例。 – Shane

+0

@chubb是否可以使用用于加密的密钥来解密值? –

+0

否HMAC是使用公钥/私钥对验证是否使用特定密钥生成哈希的单向哈希。在常规的单向散列函数(SHA1,MD5,SHA256等)中,没有涉及任何秘密密钥,因此知道算法的任何人都可以创建散列。 HMAC允许您确保只有持有特定密钥的人员/系统才会生成此散列,而不是其他人。 – chubbsondubs