亚马逊提供documentation用于验证路由到 HTTP/HTTPS 端点的 SNS 消息是否有效。在服务器上使用 Vapor 和 Swift,以及 swift-certificates和 swift-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/