Вопрос

I'm converting a php script to java (for android) but find myself stuck converting the hmac signature process.

PHP which gives correct sign:

$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==

Which is correct and accepted signature

Java (with invalid sign):

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==

The problem is in the java string conversion of the bytes (even if I add "UTF-8" as characted encoding in getBytes). I know this because if I don add path to the hmac, and just feed it with digest without the string conversion the signature matches.

Это было полезно?

Решение

After posting question I did a quick and dirty test to add bytes from path manually to a new bytes array

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));

And voilà; the hmac sign matches!

I have solved my problem but keeping question unanswered for some day to say if a better answer is provided that sheds light on this.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top