PHP: Как я могу сгенерировать подпись строки hmac SHA1?

Я пытаюсь подключиться к API с помощью PHP и мне нужна правильная подпись.

Дословно их документация:

Командная строка должна быть хеширована с использованием алгоритма хеширования HMAC SHA-1 против секретного ключа API. Результирующий массив байтов должен быть закодирован в Base64 в формате UTF-8, чтобы его можно было передать по http.

Чтобы сгенерировать подпись, вы должны перевести полный список параметров запроса в нижний регистр и отсортировать их в алфавитном порядке по полю для каждой пары поле-значение. Результирующая строка для подписи из предыдущего примера с секретным ключом VDaACYb0LV9eNjTetIOElcVQkvJck_J_QljX будет следующей:

apikey = mivr6x7u6bn_sdahobpjnejpgest35exqjb8cg20 & команда = deployvirtualmachine & serviceofferingid = 21624abb-764e-4def-81d7-9fc54b5957fb & templateid = 54c83a5e-c548-4d91-8b14-5cf2d4c081ee & ZoneId = 1128bd56-b4d9-4ac6-a7b9-c715b187ce11

В результате значение подписи:

ahlpA6J1Fq6OYI1HFrMSGgBt0WY%3D

Пример попытки:

$string = 'apikey=mivr6x7u6bn_sdahobpjnejpgest35exqjb8cg20&command=deployvirtualmachine&serviceofferingid=21624abb-764e-4def-81d7-9fc54b5957fb&templateid=54c83a5e-c548-4d91-8b14-5cf2d4c081ee&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%3D'){
    print 'SUCCESS';
}else{
    print 'FAIL';
}

РЕЗУЛЬТАТ: 9077d90baa7ab8913811b64a50814b640dce60eb

Предполагается быть: ahlpA6J1Fq6OYI1HFrMSGgBt0WY%3D

ВОПРОС: результат НЕ соответствует их документации. Есть идеи, что я сделал не так?


person Kyle Anderson    schedule 19.03.2019    source источник


Ответы (2)


Ваша подпись должна быть сгенерирована следующим образом:

$signature = urlencode(base64_encode(hash_hmac('sha1', $string , $key, true)));

Значение по умолчанию для последнего параметра — false. Затем он вернет строку в шестнадцатеричном коде вместо необработанных байтов. Затем вы должны base64_encode байты, как указано в документации. И тогда вам придется его urlencode, так как = нужно преобразовать

person kuh-chan    schedule 19.03.2019
comment
Это точно ближе. Возвращаемая подпись имеет ту же длину, что и пример документации, но не совпадает. Теперь я получаю kHfZC6p6uJE4EbZKUIFLZA3OYOs%3D вместо ожидаемого ahlpA6J1Fq6OYI1HFrMSGgBt0WY%3D - person Kyle Anderson; 19.03.2019
comment
удалить разрыв строки в вашей строке - person kuh-chan; 19.03.2019

Вы должны установить $raw_output = TRUE в hash_hmac(). Также вы должны использовать strcmp() вместо ==

Таким образом, фактический код будет



$string = 'apikey=mivr6x7u6bn_sdahobpjnejpgest35exqjb8cg20&command=deployvirtualmachine&serviceofferingid=21624abb-764e-4def-81d7-9fc54b5957fb&templateid=54c83a5e-c548-4d91-8b14-5cf2d4c081ee&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%3D'))
{
    print 'SUCCESS';
}
else
{
    print 'FAIL';
}

person Ajanyan Pradeep    schedule 19.03.2019