如何使用hash_hmac()和#34; SHA256withRSA"在PHP?

时间:2015-05-11 08:22:35

标签: php paypal webhooks

我试图让PayPal Webhooks与我的PHP应用程序一起使用。 问题是它们通过标头发送的散列算法,我必须使用它来验证请求是否有效。

当我尝试使用它时,我收到此错误:

hash_hmac(): Unknown hashing algorithm: SHA256withRSA

我使用" sha256"尝试了hash_hmac。算法和它工作,所以我认为问题必须与他们希望我使用的那个。

以下是我用来处理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
}

2 个答案:

答案 0 :(得分:0)

我认为他们没有使用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签名算法。

答案 1 :(得分:0)

以下是最终有效的代码:

// 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...

我需要解码使用base64_decode()向我发送的签名PayPal,并且出于某种原因,只有在我使用openssl_pkey_get_details()

时才能使用密钥