Friday, July 5, 2024

Invalid Signature on AWS SNS Message

Amazon Web Services has a service called Simple Notification Service, which does what it says on the tin: it sends notification messages. In my case, I was sending SNS messages to an Azure Function via HTTP calls when an email is undeliverable.

These messages have a cryptographic signature and a link to the certificate that AWS used to sign the message. You can use these to ensure the message came from AWS unchanged. Amazon has libraries to do this in various languages. I was using the .NET one.

I captured the message by having the Node-based Azure function log it to the console e.g.

console.log(request.body);

I copied the output from the Invocation list in Azure Functions and put it in a .json file.

I wrote some C# code to load the file from disk, then loaded it into an AWS SNS Message object with its ParseMessage method. Finally, I called IsMessageSignatureValid on the message. It returned false. Huh?

I suspected that something about logging it to the Azure UI or saving it to disk had somehow mangled it. Maybe something got double escaped/encoded.

To double check what AWS sending I subscribed an AWS SQS queue to it so that I could see what that captured. I knew you could look at the messages in the AWS UI.

Looks the same doesn't it? Other than the cut off UnsubscribeURL, which isn't where the problem is.

I saved it to disk and looked through it character by character. I finally noticed the one in the AWS UI had 2 spaces instead of 1 between these 2 bits:

multipart/alternative;  boundary

The AWS UI puts the contents in a <textarea> tag, which preserves all whitespace. The Azure UI uses a <span>, which does the usual HTML thing of condensing all subsequent spaces to 1, unless they are &nbsp; characters.

I put an extra space in the file I'd created from Azure's UI and IsMessageSignatureValid finally returned true.


No comments:

Post a Comment