使用 openssl_public_decrypt 发布解密 Alexa 请求签名

Issue decrypting Alexa request signature using openssl_public_decrypt

我正在为 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-encoded X.509 证书中提取 public 密钥:

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

哪个 return 是我的 public 键。然后我尝试像这样解密签名:

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

我应该 return 请求 body 的 sha1 哈希,以便我与实际请求 body 进行比较,但我从 $decryptedSignature 似乎不是 sha1 哈希。我希望我遗漏了一些明显的东西,但我看不到它。

为了让事情变得更简单,这里有一个真实的 base64_encoded 签名 header return 来自 Alexa 的测试服务:

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 中提取的 public 密钥:

-----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 验证 class 并在我通过 Alexa 认证后在此处添加 link。

编辑

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