php - 使用 openssl_public_decrypt 解密 Alexa 请求签名时出现问题

标签 php alexa-skills-kit pem php-openssl

我正在为 validating incoming requests from Amazon Alexa 实现一个验证器。我在第 5 步和第 6 步中指出:

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.

我已经通过执行以下操作从 PEM 编码的 X.509 证书中提取了公钥:

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

这会返回我的公钥。然后我尝试像这样解密签名:

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

 

这应该返回请求正文的 sha1 哈希值,以便我与实际请求正文进行比较,但我从 $decryptedSignature 返回的内容没有出现成为 sha1 哈希值。我希望我错过了一些明显的东西,但我看不到它。

为了让事情变得更简单,这是从 Alexa 测试服务返回的真实 base64_encoded 签名 header :

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

这是从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-----

最佳答案

好吧,我已经意识到我的错误了。解密的签名以二进制形式返回,因此我需要执行以下操作:bin2hex($decryptedSignature) 才能获取 sha1 哈希值。奇怪的是,返回的签名哈希值前面有 30 个额外的字符,因此实际的 Alexa 哈希值比较需要是:

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 验证类并在此处添加一个链接。

编辑

我现在已经通过认证了,所以这是我为 Alexa 验证编写的类:https://github.com/craigh411/alexa-request-validator

关于php - 使用 openssl_public_decrypt 解密 Alexa 请求签名时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46390136/

相关文章:

java - 将 .key 和 .pem 文件导入 jks 文件并在 Java/Spring 中使用

javascript - Ajax 在登录表单中显示错误而不重新加载页面

HTML 标签上的 PHP preg_match()

php - Doctrine2 存储库、多对多关联和 Twig 模板 : best practices

php - Composer 如何检查php版本?

node.js - Null SpeechletResponse 问题 (Alexa)

node.js - 如何发送到亚马逊的Alexa Event Gateway?

java - 如何使用Java代码将证书和私钥导出为单个文件?

java - 将 PEM 导入 Java keystore

node.js - Alexa 在数据返回之前做出响应