#php #hmac #hmacsha1
#php #hmac #hmacsha1
Вопрос:
Я пытаюсь подключиться к API, используя PHP, и мне нужна правильная подпись.
Их документация дословно:
Командную строку необходимо хэшировать с использованием алгоритма хэширования HMAC SHA-1 по отношению к секретному ключу API. Результирующий массив байтов должен быть закодирован на Base64 в формате UTF-8, чтобы его можно было передавать через http.
Чтобы сгенерировать подпись, вы должны ввести полный список параметров запроса в нижнем регистре и отсортировать их в алфавитном порядке по полю для каждой пары поле-значение. Результирующая строка для подписи из предыдущего примера секретным ключом VDaACYb0LV9eNjTetIOElcVQkvJck_J_QljX будет:
apikey=mivr6x7u6bn_sdahobpjnejpgest35exqjb8cg20amp;command=deployvirtualmachineamp;serviceofferingid=21624abb-764e-4def-81d7-9fc54b5957fbamp;templateid=54c83a5e-c548-4d91-8b14-5cf2d4c081eeamp;zoneid=1128bd56-b4d9-4ac6-a7b9-c715b187ce11
В результате значение сигнатуры равно:
ahlpA6J1Fq6OYI1HFrMSGgBt0WY% 3D
Пример попытки:
$string = 'apikey=mivr6x7u6bn_sdahobpjnejpgest35exqjb8cg20amp;command=deployvirtualmachineamp;serviceofferingid=21624abb-764e-4def-81d7-9fc54b5957fbamp;templateid=54c83a5e-c548-4d91-8b14-5cf2d4c081eeamp;zoneid=1128bd56-b4d9-4ac6-a7b9-c715b187ce11
';
$string = utf8_encode(strtolower($string));
$key = 'VDaACYb0LV9eNjTetIOElcVQkvJck_J_QljX';
$signature = hash_hmac('sha1', $string , $key);
print 'SIGNATURE:'.$signature.'<br>';
if($signature=='ahlpA6J1Fq6OYI1HFrMSGgBt0WY='){
print 'SUCCESS';
}else{
print 'FAIL';
}
РЕЗУЛЬТАТ: 9077d90baa7ab8913811b64a50814b640dce60eb
Предположим, что это: ahlpA6J1Fq6OYI1HFrMSGgBt0WY% 3D
ВОПРОС: Результат не соответствует их документации. Есть идеи, что я сделал не так?
Ответ №1:
Ваша подпись должна быть сгенерирована следующим образом:
$signature = urlencode(base64_encode(hash_hmac('sha1', $string , $key, true)));
Значение по умолчанию для последнего параметра равно false
. Тогда он вернет строку в шестнадцатеричном коде вместо необработанных байтов. Затем вы должны base64_encode байты, как указано в документации. И затем вам придется urlencode это, поскольку =
должно быть преобразовано
Комментарии:
1. Это определенно ближе. Возвращаемая подпись имеет ту же длину, что и в примере документации, но она не совпадает. Теперь я получаю kHfZC6p6uJE4EbZKUIFLZA3OYOs= вместо ожидаемого ahlpA6J1Fq6OYI1HFrMSGgBt0WY% 3D
2. удалите разрыв строки в вашей строке
Ответ №2:
Вы должны установить $raw_output = TRUE
в hash_hmac()
. Также вы должны использовать strcmp()
вместо ==
Таким образом, фактический код будет
$string = 'apikey=mivr6x7u6bn_sdahobpjnejpgest35exqjb8cg20amp;command=deployvirtualmachineamp;serviceofferingid=21624abb-764e-4def-81d7-9fc54b5957fbamp;templateid=54c83a5e-c548-4d91-8b14-5cf2d4c081eeamp;zoneid=1128bd56-b4d9-4ac6-a7b9-c715b187ce11
';
$string = utf8_encode(strtolower($string));
$key = 'VDaACYb0LV9eNjTetIOElcVQkvJck_J_QljX';
$signature = urlencode(base64_encode(hash_hmac('sha1', $string , $key, $raw_output=TRUE)));
print 'SIGNATURE:'.$signature.'<br>';
if(strcmp($signature,'ahlpA6J1Fq6OYI1HFrMSGgBt0WY='))
{
print 'SUCCESS';
}
else
{
print 'FAIL';
}