Issue decrypting Alexa request signature using openssl_public_decrypt

早过忘川 提交于 2019-12-22 00:00:31

问题


I'm implementing a validator for validating incoming requests from Amazon Alexa. I'm on step 5 and 6 which state:

5) base64-decode the Signature header value on the request to obtain the encrypted signature.

6) Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.

I've managed to extract the public key from the PEM-encoded X.509 certificate by doing:

$publicKey = openssl_pkey_get_public($pem);
$keyData = openssl_pkey_get_details($publicKey);

Which returns my public key. I've then attempted to decrypt the signature like so:

openssl_public_decrypt(base64_decode($this->signature), $decryptedSignature, $keyData['key']);

 

Which should return me a sha1 hash of the request body for me to compare with the actual request body, but what I get back from $decryptedSignature doesn't appear to be a sha1 hash. I'm hoping I'm missing something obvious but I can't see it.

To make things a little easier, here's a real life base64_encoded signature header returned from Alexa's test service:

DElCRMK3sXkhmnmu3D2HzVyuLHJ3JkABuBy2LCRX+winUhV6pSC9p1ASKFi9DzESsCyQ74izlFSvi3zECbSbT45bI38JpARJlal81YpWKxz2zTX+y6Qi+We/bFHHpU4gZO7nTTVQDWG4ua6EuWDTt3jL4B+hPOzO1OKix0jHKQldaTd9meyanttZ5QK7WotBeS6xU+Pum/dmiQ+LM39NERUCrCRyeU07PUdQt+L5PI8MehMz5ClHFOTWgyjE/J/b4zrX4weppb/KJhqQVmbw79BWMPuaSwf6BIHyf+4+/NSMmoaJ2WMKKEXf1aV7ac71QFFx9pw4P0BX7DK/hqy98Q==

And here is the public key extracted from https://s3.amazonaws.com/echo.api/echo-api-cert-4.pem:

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnK+zBruRA1TnbgQGxE+b 4XiTTZyDkGwJ6068AGsXQmgt9lVhC8CTTC4wdR5NXosboV6/63worQCNo412csBV jUy3H1/VEs+5Kv+AiAOUuKoBfEU8zAvHCc7GmOKUgNidcDA0MSpx3ZTMSGGbkfaL ikRzne6nFZ6jNOnkqTtGD6SrCIYgLNArScYoPzIcXEypHFrognzrR4Ee0YcefGZy S81Yqev/lli01dAgRvpnAty68rYTmxkNhzUSG6IIbFHIxXJKAETAkGiKJcgZpfG2 1Ok5Dk3yGrESY/ID5OnxvMxiXSnXwht8JD6bd15ui0tPDa85B0jpZLloqQZe26oR owIDAQAB -----END PUBLIC KEY-----


回答1:


OK, I've realised my mistake. The decrypted signature is returned in binary, so I need to do: bin2hex($decryptedSignature) in order to get the sha1 hash. Bizarrely, the returned signature hash has 30 extra chars prepended, so the actual Alexa hash comparison needs to be:

public function compareHashes($pem) {

  $publicKey = openssl_pkey_get_public($pem);

  openssl_public_decrypt(base64_decode($this->signature), $decryptedSignature, $publicKey);

  $decryptedSignature = hex2bin($decryptedSignature);

  return sha1($this->responseBody) === substr($decryptedSignature, 30);
}

Anyway, I will open source my Alexa validation class and add a link back here once I've passed Alexa certification.

Edit

I'm through certification now, so here's the class I wrote for the Alexa validation: https://github.com/craigh411/alexa-request-validator



来源:https://stackoverflow.com/questions/46390136/issue-decrypting-alexa-request-signature-using-openssl-public-decrypt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!