验证 Amazon SNS 消息签名 - Amazon Simple Notification Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

验证 Amazon SNS 消息签名

要验证 Amazon SNS 发送到您的 HTTP 端点的消息的真实性,您可以验证消息签名。在两种情况下,我们建议验证消息的真实性。第一种,当 Amazon SNS 向您的 HTTP 端点发送一条消息,说明您订阅了某个主题时。第二种,当 Amazon SNS 在执行 Subscribe 或者 Unsubscribe API 操作后,向您的 HTTP 端点发送确认消息时。

您在验证 Amazon SNS 发送的消息时应执行以下操作:

  • 从 Amazon SNS 获取证书时始终使用 HTTPS。

  • 验证证书的真伪。

  • 验证证书是否是从 Amazon SNS 收到的。

  • 尽可能使用适用于 Amazon SNS 的某个受支持 Amazon SDK 来验证消息。

  • 验证是否收到来自所需 TopicArn 的 Amazon SNS 消息。

Amazon SNS 支持两种消息签名版本:

  • SignatureVersion1:Amazon SNS 基于消息的 SHA1 哈希创建签名。

  • SignatureVersion1:Amazon SNS 基于消息的 SHA256 哈希创建签名。

在 Amazon SNS 主题上配置消息签名版本

默认情况下,Amazon SNS 主题使用 SignatureVersion 1。要在 Amazon SNS 主题上选择哈希算法 SignatureVersion 1 (SHA1) 或 SignatureVersion 2 (SHA256),可以使用 SetTopicAttributes API 操作。

以下代码示例显示如何使用 Amazon CLI 设置主题属性 SignatureVersion

aws sns set-topic-attributes \ --topic-arn arn:aws:sns:us-east-2:123456789012:MyTopic \ --attribute-name SignatureVersion \ --attribute-value 2
在使用基于 HTTP 查询的请求时验证 Amazon SNS 消息的签名
  1. 从 Amazon SNS 向终端节点发送的 HTTP POST 请求正文的 JSON 文档中提取名称/值对。您将使用名称/值对中的一些值来创建待签字符串。当您正在验证 Amazon SNS 消息签名时,应将转义控制字符转换成其在 MessageSubject 值中的原始字符表示,这点很重要。当您将上述值用作待签字符串一部分时,上述值必须保留原始形式。有关如何分析 JSON 文档的信息,请参阅 步骤 1:确保您的终端节点已准备好处理 Amazon SNS 消息

    SignatureVersion 告知您 Amazon SNS 生成消息签名所用的签名版本。通过签名版本,您可以确定生成签名的要求。对于通知,Amazon SNS 当前支持签名版本 12。本部分提供验证使用这些签名版本的签名的步骤。

  2. 获取 Amazon SNS 用于签署消息的 X509 证书。指向 X509 证书位置的 SigningCertURL 值用于创建消息的数字签名。检索此位置上的证书。

  3. 从此证书上提取公钥。来自 SigningCertURL 所指定证书的公钥用于验证信息的真实性和完整性。

  4. 确定消息类型。待签字符串格式取决于消息类型,该类型由 Type 值指定。

  5. 创建待签字符串。待签字符串为来自消息的特定名称-值对换行符逗号分隔列表。各个名称/值对由值后面换行符之后的第一个名称表示,以换行符为结尾。名称/值对必须以字节排序顺序予以列明。

    根据消息类型,待签字符串必须具有以下名称/值对。

    通知

    通知消息必须含有以下名称/值对:

    Message MessageId Subject (if included in the message) Timestamp TopicArn Type

    以下为针对 Notification 待签字符串的一个示例。

    Message My Test Message MessageId 4d4dc071-ddbf-465d-bba8-08f81c89da64 Subject My subject Timestamp 2019-01-31T04:37:04.321Z TopicArn arn:aws:sns:us-east-2:123456789012:s4-MySNSTopic-1G1WEFCOXTC0P Type Notification
    SubscriptionConfirmation 和 UnsubscribeConfirmation

    SubscriptionConfirmationUnsubscribeConfirmation 消息必须包含以下名称/值对:

    Message MessageId SubscribeURL Timestamp Token TopicArn Type

    以下为针对 SubscriptionConfirmation 待签字符串的一个示例。

    Message My Test Message MessageId 3d891288-136d-417f-bc05-901c108273ee SubscribeURL https://sns.us-east-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-east-2:123456789012:s4-MySNSTopic-1G1WEFCOXTC0P&Token=233... Timestamp 2019-01-31T19:25:13.719Z Token 233... TopicArn arn:aws:sns:us-east-2:123456789012:s4-MySNSTopic-1G1WEFCOXTC0P Type SubscriptionConfirmation
  6. 通过 Base64 格式解码 Signature 值。消息传递以 Signature 值表示的签名,并将该签名编码为 Base64。将签名值与您计算出的签名进行对比前,应确保您已通过 Base64 完成对 Signature 值的解码操作,然后才能将运用相同格式的值进行对比。

  7. 生成 Amazon SNS 消息的派生哈希值。以规范格式将 Amazon SNS 消息提交给用于生成签名的相同哈希算法。

    1. 如果 SignatureVersion1,则使用 SHA1 作为哈希算法。

    2. 如果 SignatureVersion2,则使用 SHA256 作为哈希算法。

  8. 生成 Amazon SNS 消息的断言哈希值。断言的哈希值为使用公有密钥值(来自步骤 3)对随 Amazon SNS 消息发布的签名进行解码得到的结果。

  9. 验证 Amazon SNS 信息的真实性和完整性。比较派生的哈希值(来自步骤 7)与断言的哈希值(来自步骤 8)。如果值相同,则接收人可确定消息在传输过程中未被修改,并且消息一定是源自 Amazon SNS。如果值不相同,则接收人不应信任它。