Reputation: 7416
I have an ASP.NET endpoint where I receive Amazon SNS messages. I want to verify the signatures I receive along with those messages and have followed the guide at http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.example.java.html trying to match the Java code in C#. Here's what I have so far (I'm only interested in validating notifications, not subscription confirmations):
private X509Certificate2 cert;
// cert is from constructor...
private bool IsValidMessageSignature(AmazonMessage msg)
{
// Verify the signature
var rsa = (RSACryptoServiceProvider)cert.PublicKey.Key;
var msgBytes = GetMessageBytes(msg);
var signedBytes = Convert.FromBase64String(msg.Signature);
return rsa.VerifyData(msgBytes, CryptoConfig.MapNameToOID("SHA1"), signedBytes);
}
private byte[] GetMessageBytes(AmazonMessage msg)
{
// Construct message string
var sb = new StringBuilder();
sb.AppendLine("Message");
sb.AppendLine(msg.Message);
sb.AppendLine("MessageId");
sb.AppendLine(msg.MessageId);
if (msg.Subject != null)
{
sb.AppendLine("Subject");
sb.AppendLine(msg.Subject);
}
sb.AppendLine("Timestamp");
sb.AppendLine(msg.Timestamp);
sb.AppendLine("TopicArn");
sb.AppendLine(msg.TopicArn);
sb.AppendLine("Type");
sb.AppendLine(msg.Type);
return Encoding.UTF8.GetBytes(sb.ToString());
}
The rsa.VerifyData()
step returns false. I have built the example in Java as well, and here it works fine with the same message I'm trying to validate, and the same certificate that I'm using for C#.
Here's where the two programs differ as far as I can see. The C# GetMessageBytes
byte-array returns 637 bytes, while the Java equivalent getMessageBytesToSign
returns 627 bytes. Unfortunately I cannot post the message contents here for security reasons. My Java setup uses the windows-1252 charset by default, but even if I change the C# encoding to that the byte-array is still 637 in size. I'm not that experienced with encodings and the differences between C# and Java so I don't know if it's of any importance though.
Any ideas as to how my C# should be changed?
Upvotes: 6
Views: 2069
Reputation: 1908
Amazon.SimpleNotificationService.Util.Message.ParseMessage(SNS_MESSAGE).IsMessageSignatureValid()
Upvotes: 11
Reputation: 186
It worked for me this way:
var sb = new StringBuilder();
sb.Append("Message\n");
sb.Append(notificationWrapper.Message).Append("\n");
sb.Append("MessageId\n");
sb.Append(notificationWrapper.MessageId).Append("\n");
if (notificationWrapper.Subject != null)
{
sb.Append("Subject\n");
sb.Append(notificationWrapper.Subject).Append("\n");
}
sb.Append("Timestamp\n");
sb.Append(notificationWrapper.Timestamp).Append("\n");
sb.Append("TopicArn\n");
sb.Append(notificationWrapper.TopicArn).Append("\n");
sb.Append("Type\n");
sb.Append(notificationWrapper.Type).Append("\n");
return Encoding.UTF8.GetBytes(sb.ToString());
Upvotes: 0
Reputation: 5744
The Java code ends lines with \n
. The C# version (StringBuilder.AppendLine()
) uses \r\n
.
Upvotes: 0