C#验证签名 [英] C# Validate Signature
问题描述
我有以下代码在发送数据之前签名(http):
I have the following code to sign my data before sending it (http):
internal static byte[] Encode(byte[] arMessage, string signerCert, string signerPassword)
{
X509Certificate2 cert = new X509Certificate2(signerCert, signerPassword);
//debug data
var msg = System.Text.ASCIIEncoding.ASCII.GetString(arMessage);
//--
ContentInfo contentInfo = new ContentInfo(arMessage);
SignedCms signedCms = new SignedCms(contentInfo, true); // <- true detaches the signature
CmsSigner cmsSigner = new CmsSigner(cert);
signedCms.ComputeSignature(cmsSigner);
byte[] signature = signedCms.Encode();
return signature;
}
我可以在执行以下操作后看到签名:
I can see the signature after doing the following:
string sig = Convert.ToBase64String(bSignature) + MESSAGE_SEPARATOR;
//this will be included in the message:
bSignature = System.Text.ASCIIEncoding.ASCII.GetBytes(sig);
//debug data, see the signature:
string deb8 = System.Text.ASCIIEncoding.ASCII.GetString(bSignature);
//--
例如:
MIICvgYJKoZIhvcNAQcCoIICrzCCAqsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCCAbgwggG0MIIBXqADAgECAhAGicJ2MhB7tUZtG3QcdWDwMA0GCSqGSIb3DQEBBAUAMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5MB4XDTExMDUwMzEyMTQ0NVoXDTM5MTIzMTIzNTk1OVowDzENMAsGA1UEAxMEVGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuOm4jGHUzLPNww6sx7cZJJxjLIDL/rVVLOtDd1NeA4DZZM1+lKwLpDp3FrV1CA4NP7g3weTg6Y0Jb6X7CSQHnfHRzU8LLrHgp/D9NJ39/RhsKggUteMa1FUUas0fMDMELtTO07ejNfYAhDYQiXmeg+pIMpUfeUhMicyV2xrPzG8CAwEAAaNLMEkwRwYDVR0BBEAwPoAQEuQJLQYdHU8AjWEh3BZkY6EYMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5ghAGN2wAqgBkihHPuNSqXDX0MA0GCSqGSIb3DQEBBAUAA0EAVIjI0My490lY6vKrcgorZZ8MBo3MSk9HuDRBE0SRwSQjnvPsAD0ol1ZjvzjFKA/0Vgvp1lyYquCTSL8R/uWf+TGBzzCBzAIBATAqMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5AhAGicJ2MhB7tUZtG3QcdWDwMAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYCuXG2CJ0G6UaO1AVMpo5ul3JkJ9EvJbdwb6sXOqOonq5qKbaGJsx0sgwoBfg3lLMP3UI9JVi4dTGG4KTzA1k/0Qt0owmEPKrDh3zVZr2hK/iHsW75sGjSgYT4hxbn6ziQ2IFoN2qCbxdXrMZ+TD0pf7o/ABdorjlvQ5USwlPKjZQ==
这是我在收到的消息。
因此问题是:如何验证收件人上收到的邮件的签名(提供了.cer文件)?
提前感谢
This is what I have in the received message. So the question is: how to validate the signature of the received message on the recipient (has the .cer file provided)? Thanks in advance
编辑1:
我试图遵循Daniel Hilgarth的逻辑,没有工作。
我几次遇到ASN坏标记值异常。
为了更容易,我硬编码用于生成签名的消息
所以,在接收器我有2件事情:原始消息和为它生成的签名:
I tried to follow the Daniel Hilgarth's logic but it didn't worked. A few times I met the "ASN Bad tag value" exception. To make it easier, I hardcoded the message being used to generate the signature So, on the receiver I have 2 things: the original message and the signature generated for it:
//Signature from the message (string in ASCII)
var signatureKey = GetSignatureFromSignatureMessage(signatureMessage, boundary);
//Original sent message (the arMessage itself used in Encode method above, converted to string from byte)
var messageOriginal =
"Content-Type: application/EDIFACT\r\nContent-Transfer-Encoding: binary\r\n\r\nSome short text.\r\nVery short.";
我需要检查签名是否对应此邮件。
所以我试图做这样的事情:
I need to check if the signature corresponds this message. So I am trying to do something like this:
//contentInfo from the original message.
ContentInfo contentInfo = new ContentInfo(System.Text.ASCIIEncoding.ASCII.GetBytes(messageOriginal));
//SingedCms from the contentInfo above
SignedCms signedCms = new SignedCms(contentInfo, true);
//Here, I believe, I am attaching the signature I have to the Cms
signedCms.Decode(System.Text.ASCIIEncoding.ASCII.GetBytes(signatureKey));
//checking?
signedCms.CheckSignature(true);
我在解码部分获得异常。
And I get exceptions on decode part.
任何建议?
编辑2:
解决方案:
Daniel Hilgarth给出的指示是正确的。
我的问题是发送者编码的关键几次:
Base64字节数组 - > Base64String - > ASCII字节数组 - > ASCII字符串 - > Send_message
接收器接收数据在ASCII已经,做:
ASCII字符串 - >字节数组。
我必须将一切都转换回base64字节数组,使其工作。
Edit 2: Solution: The direction given by Daniel Hilgarth is right. My problem was that the sender encoded the key few times: Base64 byte array -> Base64String -> ASCII byte array -> ASCII string -> Send_message The receiver was receiving the data in ASCII already, doing: ASCII String -> Byte array. I had to convert everything back to base64 byte array to make it work.
//Signature from the message (ASCII String)
var signatureKey = GetSignatureFromSignatureMessage(signatureMessage, boundary);
//Original Byte Array (Base64)
var sigKeyBase = Convert.FromBase64String(signatureKey);
//Original sent message
var messageOriginal =
"Content-Type: application/EDIFACT\r\nContent-Transfer-Encoding: binary\r\n\r\nSome short text.\r\nVery short.";
var messageOriginalByteASCII = System.Text.ASCIIEncoding.ASCII.GetBytes(messageOriginal);
ContentInfo contentInfo = new ContentInfo(messageOriginalByteASCII);
SignedCms signedCms = new SignedCms(contentInfo, true);
signedCms.Decode(sigKeyBase);
signedCms.CheckSignature(true);
在这种情况下,它通过检查。
P.S.太糟糕的ChekSignature不返回true或false。我会更舒服的imho。 :
In this case it passes Check. P.S. Too bad ChekSignature doesn't return true or false. I'd be more comfortable imho. :(
推荐答案
Hm ...也许使用 SignedCms.CheckSignature
?与 SignedCms。解码
。基本上,只需使用与您用于签名文档相反的方式,可以从MSDN页面获得具有分离签名的示例:
Hm... maybe using SignedCms.CheckSignature
?! Use it in conjunction with SignedCms.Decode
. Basically, just use the reverse way you use to sign the document. An example with detached signature is available from the MSDN page:
// Create a ContentInfo object from the inner content obtained
// independently from encodedMessage.
ContentInfo contentInfo = new ContentInfo(innerContent);
// Create a new, detached SignedCms message.
SignedCms signedCms = new SignedCms(contentInfo, true);
// encodedMessage is the encoded message received from
// the sender.
signedCms.Decode(encodedMessage);
// Verify the signature without validating the
// certificate.
signedCms.CheckSignature(true);
这篇关于C#验证签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!