这是后续this https://stackoverflow.com/questions/7175067/hmc-sha1-hash-c-sharp-producing-different-hash-output-than-ruby问题,但我正在尝试将 C# 代码移植到 Java,而不是将 Ruby 代码移植到 C#,就像相关问题中的情况一样。我正在尝试验证加密的签名 http://docs.recurly.com/recurlyjs/signatures从 Recurly.js api 返回是有效的。不幸的是,Recurly 没有 Java 库来协助验证,因此我必须自己实现签名验证。
根据上述相关问题(this https://stackoverflow.com/questions/7175067/hmc-sha1-hash-c-sharp-producing-different-hash-output-than-ruby),以下 C# 代码可以生成验证从 Recurly 返回的签名所需的哈希值:
var privateKey = Configuration.RecurlySection.Current.PrivateKey;
var hashedKey = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(privateKey));
var hmac = new HMACSHA1(hashedKey);
var hash = hmac.ComputeHash(Encoding.ASCII.GetBytes(dataToProtect));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
Recurly 提供了以下有关其的示例数据签名 http://docs.recurly.com/recurlyjs/signatures文档页面:
未加密的验证消息:
[1312701386,transactioncreate,[账户代码:ABC,金额:5000,货币:美元]]
私钥:
0123456789ABCDEF0123456789ABCDEF
生成的签名:
0f5630424b32402ec03800e977cd7a8b13dbd153-1312701386
这是我的 Java 实现:
String unencryptedMessage = "[1312701386,transactioncreate,[account_code:ABC,amount_in_cents:5000,currency:USD]]";
String privateKey = "0123456789ABCDEF0123456789ABCDEF";
String encryptedMessage = getHMACSHA1(unencryptedMessage, getSHA1(privateKey));
private static byte[] getSHA1(String source) throws NoSuchAlgorithmException, UnsupportedEncodingException{
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] bytes = md.digest(source.getBytes("UTF-8"));
return bytes;
}
private static String getHMACSHA1(String baseString, byte[] keyBytes) throws GeneralSecurityException, UnsupportedEncodingException {
SecretKey secretKey = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKey);
byte[] bytes = baseString.getBytes("ASCII");
return Hex.encodeHexString(mac.doFinal(bytes));
}
但是,当我打印出 cryptoMessage 变量时,它与示例签名的消息部分不匹配。具体来说,我得到的值是“c8a9188dcf85d1378976729e50f1de5093fabb78”,而不是“0f5630424b32402ec03800e977cd7a8b13dbd153”。
Update
根据@M.Babcock,我使用示例数据重新运行了 C# 代码,它返回了与 Java 代码相同的输出。所以看来我的散列方法是正确的,但我传递了错误的数据(未加密的消息)。叹。如果/当我可以确定要加密的正确数据是什么时,我将更新这篇文章 - 因为 Recurly 文档中提供的“未加密验证消息”似乎缺少某些内容。
Update 2
错误结果是“未加密的验证消息”数据/格式。示例数据中的消息实际上并未加密到提供的示例签名 - 所以文档可能已经过时了?无论如何,我已经确认 Java 实现适用于现实世界的数据。谢谢大家。