我在Android上遇到了一些HMAC问题。我正在使用SHA1算法,以下代码在搜索android hmac-sha1时显示在整个网络上。
String base_string = "This is a test string";
String key = "testKey";
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec secret = new SecretKeySpec(key.getBytes("UTF-8"), mac.getAlgorithm());
mac.init(secret);
byte[] digest = mac.doFinal(base_string.getBytes());
String enc = new String(digest);
// Base 64 Encode the results
String retVal = Base64.encodeBase64String(enc.getBytes());
Log.v(TAG, "String: " + base_string);
Log.v(TAG, "key: " + key);
Log.v(TAG, "result: " + retVal);
} catch (Exception e) {
System.out.println(e.getMessage());
}
为了测试这段代码,我用它创建了一个简单的标准Java程序(当然用System.out.println调用替换Log.v调用)所以我可以与android版本进行比较。在这两个实例中,我使用的是base_string和key的相同测试值。
此外,我已经使用一些PHP函数和验证服务器(使用一些OAuth令牌)验证了标准Java的编码结果。代码在标准Java程序中运行良好,但它在Android程序中不起作用。我做了很多搜索,无法弄清楚出了什么问题。有没有人经历过这个?
以下是标准java和android ...
的结果fH/+pz0J5XcPZH/d608zGSn7FKA=
fH/vv73vv709Ce+/vXcPZH/vv73vv71PMxkp77+9FO+/vQ==
进一步研究我确定它是hmac函数而不是Base64编码,因为比较那些hmac值,Android版本具有各种额外空格和其他未知字符符号而不是Java程序
感谢任何帮助!
答案 0 :(得分:13)
我认为这是一个字符串编码问题。
你在这做什么?
String enc = new String(digest);
// Base 64 Encode the results
String retVal = Base64.encodeBase64String(enc.getBytes());
你转换一个字符串中的字节,然后再转回一个字节数组(然后你进行base-64编码)。
相反,这样做:
String retVal = Base64.encodeBase64String(digest);
一般情况下,如果您想要便携式程序,请永远不要使用String.getBytes()
或new String(byte[])
。并且永远不要尝试将任意字节数组(之前不是字符串)转换为字符串(除了像Base64之类的东西)。