我正在将一个PHP脚本转换为java(用于android),但发现自己陷入了转换hmac签名过程。
PHP给出了正确的符号:
$secret = "lT4fhviR7ILvwGeiBJgolfYji1uz/f7B6HQWaWQWVl/sWEz3Kwt4QjzCHWE+MBENOmtgBS6PlN87s+1d7/8bRw==";
$nonce = "1388256620813308";
$postdata = "nonce=1388256620813308";
$path = "/0/private/Balance";
$sign = hash_hmac('sha512', $path . hash('sha256', $nonce . $postdata, true), base64_decode($this->secret), true);
echo $sign;
Hmac = 2IVoBCoadCEivxKVRB / 4quJET4DoZV4JdY6bMC2oEYJZuygF5JiAhGrxVMyw2yPhz + KdiwvbzV43cicGamzr2A ==
哪个是正确且接受的签名
Java(带有无效符号):
String secret = "lT4fhviR7ILvwGeiBJgolfYji1uz/f7B6HQWaWQWVl/sWEz3Kwt4QjzCHWE+MBENOmtgBS6PlN87s+1d7/8bRw==";
String nonce = "1388256620813308";
String postdata = "nonce=1388256620813308";
String path = "/0/private/Balance";
// hash nonce + data
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update((nonce+postdata).getBytes());
byte[] digest = md.digest();
String baseString = path + new String(digest); //this is probably root of evil
// HMAC
Mac mac = Mac.getInstance("HmacSHA512");
SecretKey secretKey = new SecretKeySpec(Base64.decode(secret, Base64.DEFAULT), "HmacSHA512");
mac.init(secretKey);
String sign = new String(Base64.encodeToString(mac.doFinal(baseString.getBytes()), Base64.DEFAULT)).trim();
Log.d(TAG, sign);
Hmac = 7ZQfn + fqMpMEFN5Z / T5UwcqP1uo0JOyAVSn4HEBeE / KotnEf4a5bPOWriiC // gdoEg2kOe60EIr3Lv7irXuejw ==
问题在于字节的java字符串转换(即使我在getBytes
中添加“UTF-8”作为characted编码)。我知道这一点,因为如果我不将path
添加到hmac,只需将digest
与{{1}}一起提供,而不进行字符串转换,则签名会匹配。
答案 0 :(得分:0)
发布问题后,我做了一个快速而肮脏的测试,将path
的字节手动添加到新的字节数组
byte[] digest = md.digest();
byte[] pBytes = path.getBytes();
int L = digest.length + pBytes.length;
byte[] message = new byte[L];
for (int i=0;i<pBytes.length;i++) {
message[i] = pBytes[i];
}
for (int i=pBytes.length,n=0; n<digest.length; n++) {
message[i+n] = digest[n];
}
String sign = new String(Base64.encodeToString(mac.doFinal(message), Base64.NO_WRAP));
瞧! hmac标志匹配!
我已经解决了我的问题,但有一天仍然没有回答问题,如果提供了一个更好的答案来阐明这一点。