我在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 token )验证了标准Java的编码结果。该代码在标准Java程序中可以正常工作,但在Android程序中则无法工作。我进行了很多搜索,无法找出问题所在。任何人都经历过吗?
这是标准Java和android的结果...
fH/+pz0J5XcPZH/d608zGSn7FKA=
fH/vv73vv709Ce+/vXcPZH/vv73vv71PMxkp77+9FO+/vQ==
进一步研究它,我可以确定它是hmac函数,而不是Base64编码,因为比较这些hmac值时,Android版本与Java程序相比具有各种额外的空格和其他未知字符符号。
任何帮助表示赞赏!
最佳答案
我想这是一个字符串编码问题。
你在这里做什么?
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的字符串)。