问题描述
我正在为 验证来自 Amazon Alexa 的传入请求.我在第 5 步和第 6 步中指出:
I'm implementing a validator for validating incoming requests from Amazon Alexa. I'm on step 5 and 6 which state:
5) 对请求中的 Signature 标头值进行 base64 解码以获得加密签名.
6) 使用从签名证书中提取的公钥对加密的签名进行解密,以生成断言的哈希值.
6) Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
我已经设法从 PEM 编码的 X.509 证书中提取了公钥,方法如下:
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']);
哪个应该返回请求正文的 sha1
哈希值以便我与实际请求正文进行比较,但是我从 $decryptedSignature
返回的内容没有出现成为 sha1
哈希.我希望我遗漏了一些明显但我看不到的东西.
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.
为了让事情更简单,这里有一个真实的 base64_encoded
签名标头,从 Alexa 的测试服务返回:
To make things a little easier, here's a real life base64_encoded
signature header returned from Alexa's test service:
DElCRMK3sXkhmnmu3D2HzVyuLHJ3JkABuBy2LCRX + winUhV6pSC9p1ASKFi9DzESsCyQ74izlFSvi3zECbSbT45bI38JpARJlal81YpWKxz2zTX + y6Qi +我们/bFHHpU4gZO7nTTVQDWG4ua6EuWDTt3jL4B + hPOzO1OKix0jHKQldaTd9meyanttZ5QK7WotBeS6xU + PUM/dmiQ + LM39NERUCrCRyeU07PUdQt + L5PI8MehMz5ClHFOTWgyjE/J/b4zrX4weppb/KJhqQVmbw79BWMPuaSwf6BIHyf + 4 +/NSMmoaJ2WMKKEXf1aV7ac71QFFx9pw4P0BX7DK/hqy98Q ==
这里是从 https://s3.amazonaws.com/echo.api/echo-api-cert-4.pem:
-----开始公钥-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnK+zBruRA1TnbgQGxE+b4XiTTZyDkGwJ6068AGsXQmgt9lVhC8CTTC4wdR5NXosboV6/63worQCNo412csBVjUy3H1/VEs+5Kv+AiAOUuKoBfEU8zAvHCc7GmOKUgNidcDA0MSpx3ZTMSGGbkfaLikRzne6nFZ6jNOnkqTtGD6SrCIYgLNArScYoPzIcXEypHFrognzrR4Ee0YcefGZyS81Yqev/lli01dAgRvpnAty68rYTmxkNhzUSG6IIbFHIxXJKAETAKGiKJcgZpfG21Ok5Dk3yGrESY/ID5OnxvMxiXSnXwht8JD6bd15ui0tPDa85B0jpZLloqQZe26oRowIDAQAB-----结束公钥-----
推荐答案
好的,我已经意识到我的错误了.解密后的签名以二进制形式返回,因此我需要执行: bin2hex($decryptedSignature)
以获得 sha1
哈希值.奇怪的是,返回的签名哈希有 30 个额外的字符,所以实际的 Alexa 哈希比较需要是:
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);
}
无论如何,我将开源我的 Alexa 验证类,并在我通过 Alexa 认证后在此处添加一个链接.
Anyway, I will open source my Alexa validation class and add a link back here once I've passed Alexa certification.
编辑
我现在通过了认证,所以这是我为 Alexa 验证编写的类:https://github.com/craigh411/alexa-request-validator
I'm through certification now, so here's the class I wrote for the Alexa validation: https://github.com/craigh411/alexa-request-validator
这篇关于使用 openssl_public_decrypt 解密 Alexa 请求签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!