验证 Alexa 请求的签名

Verifying the signature of an Alexa request

我目前正在构建一个应该处理 Alexa 语音意图的网络服务。我从 Alexa 获得的 HTTP 请求必须通过检查签名来验证,如 documentation 中所述(摘录见下文)。

我似乎正确地解密了请求中发送的签名,并且似乎正确地计算了请求正文的签名。但它们不同——但不是完全不同(这会暗示计算中存在某些错误),计算出的签名是发送签名的后缀。例如:

收到签名(解码解密):

3021300906052b0e03021a05000414ca5cc3be233b045be79e94389e47353b7aaec434

请求正文的计算签名(其 sha1 哈希):

ca5cc3be233b045be79e94389e47353b7aaec434

收到的签名开头多出的字节是什么?它们似乎在请求之间没有变化。

各种信息:

Checking the Signature of the Request

Requests sent by Alexa provide the information you need to verify the signature in the HTTP headers:

  • SignatureCertChainUrl
  • Signature

To validate the signature:

  • Verify the URL specified by the SignatureCertChainUrl header value on the request to ensure that it matches the format used by Amazon. See Verifying the Signature Certificate URL.

  • Download the PEM-encoded X.509 certificate chain that Alexa used to sign the message as specified by the SignatureCertChainUrl header value on the request.

  • This chain is provided at runtime so that the certificate may be updated periodically, so your web service should be resilient to different URLs with different content.

  • This certificate chain is composed of, in order, (1) the Amazon signing certificate and (2) one or more additional certificates that create a chain of trust to a root certificate authority (CA) certificate. To confirm the validity of the signing certificate, perform the following checks:
    • The signing certificate has not expired (examine both the Not Before and Not After dates)
    • The domain echo-api.amazon.com is present in the Subject Alternative Names (SANs) section of the signing certificate
    • All certificates in the chain combine to create a chain of trust to a trusted root CA certificate
  • Once you have determined that the signing certificate is valid, extract the public key from it.
  • Base64-decode the Signature header value on the request to obtain the encrypted signature.
  • Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
  • Generate a SHA-1 hash value from the full HTTPS request body to produce the derived hash value
  • Compare the asserted hash value and derived hash values to ensure that they match

通过 google 搜索已发送签名的前缀 3021300906052b0e03021a05000414,我发现 the prefix is a constant that indicates the used hash algorithm。要么将其切断,要么让 OpenSSL 进行签名验证即可解决问题。永远不要酿造自己的加密货币!