C# 验证签名

本文关键字:验证 | 更新日期: 2023-09-27 17:55:09

我有以下代码在发送数据之前对数据进行签名(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;
            }

执行以下操作后,我可以看到签名:

    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文件)?提前致谢

编辑 1:

我试图遵循丹尼尔·希尔加斯的逻辑,但没有奏效。有几次我遇到"ASN 错误标记值"异常。为了方便起见,我对用于生成签名的消息进行了硬编码因此,在接收器上,我有两件事:原始消息和为其生成的签名:

    //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.";

我需要检查签名是否与此消息相对应。所以我正在尝试做这样的事情:

//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);

我在解码部分遇到异常。

有什么建议吗?

编辑 2:溶液:丹尼尔·希尔加斯给出的方向是正确的。我的问题是发送者对密钥进行了几次编码:Base64 字节数组 -> Base64String -> ASCII 字节数组 -> ASCII 字符串 -> Send_message接收方已经在接收 ASCII 格式的数据,正在执行以下操作:ASCII 字符串 -> 字节数组。我必须将所有内容转换回 base64 字节数组才能使其工作。

    //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);

在这种情况下,它通过检查。附言太糟糕了 ChekSignature 不返回真或假。恕我直言,我会更舒服。:(

C# 验证签名

嗯......也许使用SignedCms.CheckSignature?!将其与SignedCms.Decode结合使用。基本上,只需使用您用来签署文档的相反方式。MSDN 页面中提供了具有分离签名的示例:

// 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);