swift - 如何验证服务器端 Swift HTTPS 端点中的 SNS 消息?

标签 swift cryptography amazon-sns vapor

亚马逊提供documentation用于验证路由到 HTTP/HTTPS 端点的 SNS 消息是否有效。在服务器上使用 Vapor 和 Swift,以及 swift-certificatesswift-crypto ,我实现了验证逻辑:

func messageHasValidSignature<Message: VerifiableMessage>(_ message: Message) async throws -> Bool {
    guard let certificateBytes = try await client.get(.init(message.signingCertificateURL)).body else {
        logger.error("Failed to get signing certificate body")
        throw Abort(.badRequest)
    }

    let certificateString = String(buffer: certificateBytes)
    let certificate = try Certificate(pemEncoded: certificateString)
    let publicKey = try _RSA.Signing.PublicKey(derRepresentation: certificate.publicKey.subjectPublicKeyInfoBytes)
    guard let signatureData = Data(base64Encoded: message.signature) else {
        logger.error("Failed to decode signature")
        throw Abort(.badRequest)
    }

    let signature = _RSA.Signing.RSASignature(rawRepresentation: signatureData)

    guard let dataToSign = message.stringToSign.data(using: .utf8) else {
        logger.error("Failed to convert string to sign to data")
        throw Abort(.badRequest)
    }

    let digest: any Digest
    switch message.signatureVersion {
    case ._1:
        digest = Insecure.SHA1.hash(data: dataToSign)
    case ._2:
        digest = SHA256.hash(data: dataToSign)
    }

    return publicKey.isValidSignature(signature, for: digest)
}

我正在构建要签名的字符串,如下所示:

extension SubscriptionConfirmationMessage: VerifiableMessage {
    var stringToSign: String {
        """
        Message
        \(message)
        MessageId
        \(messageID)
        SubscribeURL
        \(subscribeURL)
        Timestamp
        \(timestamp)
        Token
        \(token)
        TopicArn
        \(topicARN)
        Type
        SubscriptionConfirmation

        """
    }
}

但是 isValidSignature 始终返回 false。如何正确验证消息?

最佳答案

问题在于传递给 isValidSignature 的填充。默认值为 PSS(“使用 MGF1 的 PSS 填充”)。通过检查C# implementation的来源我发现它应该是insecurePKCS1v1_5(“PKCS#1 v1.5”)。

所以验证签名的正确方法是:

return publicKey.isValidSignature(signature, for: digest,  padding: .insecurePKCS1v1_5)

关于swift - 如何验证服务器端 Swift HTTPS 端点中的 SNS 消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77649510/

相关文章:

c# - 尝试实例化新的 RSACryptoServiceProvider 时出现 "Keyset does not exist"

amazon-web-services - 将AWS SNS消息发布到Pagerduty

ios - Swift 数组和字典性能,removeAll() 与新实例

ios - 无法在代码中创建 UIToolBar

swift - 如何快速理解 "first-class function"?

python - 自定义 LIBFFI Heroku buildpack 的问题

ios - UIViewController 的子类所需的初始值设定项

python - Python 中的 AES 加密 - 使用 pycryptodome 和加密技术时的不同结果

amazon-s3 - Terraform s3 事件通知错误

amazon-s3 - 如何将原始电子邮件 (MIME) 从 AWS SES 转换为 Gmail?