Как использовать hash_hmac () с SHA256withRSA на PHP?

Я пытаюсь заставить PayPal Webhooks работать с моим приложением PHP. Проблема заключается в алгоритме хеширования, который они отправляют через заголовки, которые я должен использовать, чтобы проверить, действителен ли запрос.

Когда я пытаюсь его использовать, я получаю такую ​​ошибку:

hash_hmac(): Unknown hashing algorithm: SHA256withRSA

Я пробовал hash_hmac, используя только алгоритм «sha256», и он сработал, поэтому я думаю, что проблема должна быть в том, который они хотят, чтобы я использовал.

Вот код, который я использую для обработки Webhook:

$headers = apache_request_headers();

$body = @file_get_contents('php://input');
$json = json_decode($body);

// Concatanate the reqired strings values
$sigString = $headers['PAYPAL-TRANSMISSION-ID'].'|'.$headers['PAYPAL-TRANSMISSION-TIME'].'|'.$json->id.'|'.crc32($body);

// Get the certificate file and read the key
$pub_key = openssl_pkey_get_public(file_get_contents($headers['PAYPAL-CERT-URL']));
$keyData = openssl_pkey_get_details($pub_key);

// check signature
if ($headers['PAYPAL-TRANSMISSION-SIG'] != hash_hmac($headers['PAYPAL-AUTH-ALGO'],$sigString,$keyData['key'])) {
    //invalid
}

person user3305874    schedule 11.05.2015    source источник


Ответы (2)


Я думаю, что они используют не алгоритм HMAC (симметричный), вопреки тому, что говорится в документации, а RSA (асимметричный). Поэтому вам следует использовать openssl_verify для проверки подписи. Может, это сработает:

//your code here...

// Get the certificate file and read the key
$pubKey = openssl_pkey_get_public(file_get_contents($headers['PAYPAL-CERT-URL']));

$verifyResult = openssl_verify($sigString, $headers['PAYPAL-TRANSMISSION-SIG'], $pubKey, 'sha256WithRSAEncryption');

if ($verifyResult === 0) {
    throw new Exception('signature incorrect');
} elseif ($verifyResult === -1) {
    throw new Exception('error checking signature');
}

//rest of the code when signature is correct...

Имена алгоритмов подписи, используемые PayPal, могут отличаться от используемых в PHP. Обратитесь к методу openssl_get_md_methods, чтобы получить действительные алгоритмы подписи PHP.

person Furgas    schedule 11.05.2015
comment
Пришлось немного изменить Ваш код, и вот, наконец, это сработало! Спасибо, что направили меня в правильном направлении. - person user3305874; 01.06.2015

Вот код, который в итоге сработал:

// Get the certificate file and read the key
$pubKey = openssl_pkey_get_public(file_get_contents($headers['PAYPAL-CERT-URL']));
$details = openssl_pkey_get_details($pubKey);

$verifyResult = openssl_verify($sigString, base64_decode($headers['PAYPAL-TRANSMISSION-SIG']), $details['key'], 'sha256WithRSAEncryption');

if ($verifyResult === 0) {
    throw new Exception('signature incorrect');
} elseif ($verifyResult === -1) {
    throw new Exception('error checking signature');
}

//rest of the code when signature is correct...

Мне нужно было расшифровать подпись, которую PayPal отправил мне с base64_decode(), и по какой-то причине ключ работал только тогда, когда я использовал openssl_pkey_get_details()

person user3305874    schedule 01.06.2015