I'm not very knowledgeable in SSL and certificates. I used the post "How to use hash_hmac() with "SHA256withRSA" on PHP?" to see if I can get webhooks with PayPal working.
The issue I am have is I am getting the following error after calling openssl_verify()
and a return result of (0):
OpenSSL error openssl_verify error:04091068:rsa routines:INT_RSA_VERIFY:bad signature
I've tried to solve this, but documentation on errors and the functions around the web is minimal to none.
My current code looks like this:
// get the header post to my php file by PayPal
$headers = apache_request_headers();
// get the body post to me php file by PayPal
$body = @file_get_contents('php://input');
$json = json_decode($body);
// TransmissionId|TransmissionTimeStamp|WebhookId|CRC32 as per PayPal documentation
$sigString = $headers['Paypal-Transmission-Id'].'|'.$headers['Paypal-Transmission-Time'].'|'.$json->id.'|'.crc32($body);
// $headers['Paypal-Cert-Url'] contains the "-----BEGIN CERTIFICATE---MIIHmjCCBoKgAwIBAgIQDB8 ... -----END CERTIFICATE-----"
$pubKey = openssl_pkey_get_public(file_get_contents($headers['Paypal-Cert-Url']));
// and this is the call to verify that returns result (0)
$verifyResult = openssl_verify($sigString, base64_decode($headers['Paypal-Transmission-Sig']), $pubKey, 'sha256WithRSAEncryption');
Only different from the reference code I used, is that I do not use openssl_pkey_get_details($pubKey)
because I will get below error in addition to the existing signature error:
OpenSSL error openssl_verify error:0906D06C:PEM routines:PEM_read_bio:no start line OpenSSL error openssl_verify error:04091068:rsa routines:INT_RSA_VERIFY:bad signature
Also I've tried a variation by not using base64_decode()
on the header but that would get the same return result (0) with error stating:
OpenSSL error openssl_verify error:04091077:rsa routines:INT_RSA_VERIFY:wrong signature length
What is wrong with the signature?
You may want to use this piece of code:
$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');
}
The formula is <transmissionId>|<timeStamp>|<webhookId>|<crc32>
not <transmissionId>|<timeStamp>|<eventId>|<crc32>
. Also note that Webhook simulator events can't be verified.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With