创建与OpenSSL SMIME命令兼容的PKCS#7 CMS独立签名

时间:2019-06-07 16:01:00

标签: c# openssl pkcs#7 message-digest

我正在尝试创建XML文件的分离签名,以便将消息发送给政府组织。政府方面的应用程序希望PKCS#7分离的签名没有证书和数据(?)。在文档中,他们以openssl为例。在字符串“ this is string”(不带引号)中,openssl命令:

  

openssl smime -sign -outform pem -signer C:\ Temp \ cert_test_np.pem -in   C:\ Temp \ test.xml -out C:\ Temp \ Podpis2.xml -nocerts

生成此签名字符串

  

----- BEGIN PKCS7 ----- MIIC0QYJKoZIhvcNAQcCoIICwjCCAr4CAQExDzANBglghkgBZQMEAgEFADALBgkq   hkiG9w0BBwExggKZMIIClQIBATCBhjB / MQswCQYDVQQGEwJDWjEoMCYGA1UEAwwf   SS5DQSBUZXN0IFB1YmxpYyBDQS9SU0EgMTEvMjAxNTEtMCsGA1UECgwkUHJ2bsOt   IGNlcnRpZmlrYcSNbsOtIGF1dG9yaXRhLCBhLnMuMRcwFQYDVQQFEw5OVFJDWi0y   NjQzOTM5NQIDAU1jMA0GCWCGSAFlAwQCAQUAoIHkMBgGCSqGSIb3DQEJAzELBgkq   hkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE5MDYwNzE1MjcyMFowLwYJKoZIhvcN   AQkEMSIEIDY + iM9Vpap9krHOHyxKSyBHRZM20eaMwQFR7OpqrryFMHkGCSqGSIb3   DQEJDzFsMGowCwYJYIZIAWUDBAEqMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIw   CgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsO   AwIHMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAIeN8SPBeNfDmip0   NrpCoJ7c7YuuDW36OE9TN30D / ijRWcNMdgsObyNTFSrY0 / 51Gy655kejppfhwicv   l / AdEXZcmM8JoWR9vHeRcklWmHLn1XYnKhDDWSQMZ0Kp62TTBTBsA6dLjizOhWx0   u4Rj / lVv5 / PmGsrQ4JmNreCaoSBAdqYOFCy2ZrvWNfhvpKPE + SDlAVMayfY0nqwM   ds5pSb5o + YAWgsbfSQQU7uJp2K8XU4B1YAvGsg + aoGOxf / uiWNoppluQ9hpFAMzx   tqndj8d1E2MUGkc6rISrMv + eoNheU + RM9ovDHQh9IVUDrdq8IalnjYVFsj + / 0Wcz   1O14IY0 =   ----- END PKCS7 -----

我已经用C#编写了以下代码

 public static string GetSignatureString(string stringToSign, X509Certificate2 certificateToUse)
        {
            byte[] array = Encoding.ASCII.GetBytes(stringToSign);
            ContentInfo content = new ContentInfo(array);
            certificate = certificateToUse;
            SignedCms signedCMS = new SignedCms(content, true);

            CmsSigner signer = new CmsSigner(certificate);
            signer.IncludeOption = X509IncludeOption.None;
            signer.DigestAlgorithm =new Oid("2.16.840.1.101.3.4.2.1");
            signer.SignedAttributes.Add(new Pkcs9SigningTime());

            signedCMS.ComputeSignature(signer, true);
            byte[] signed = signedCMS.Encode();

            string sToWrite = Convert.ToBase64String(signed,Base64FormattingOptions.InsertLineBreaks);
            return "-----BEGIN PKCS7-----\r\n" + sToWrite + "\r\n-----END PKCS7-----\r\n";
        }

将返回以下PKCS#7字符串

  

----- BEGIN PKCS7 ----- MIICVQYJKoZIhvcNAQcCoIICRjCCAkICAQExDzANBglghkgBZQMEAgEFADALBgkqhkiG9w0BBwEx   ggIdMIICGQIBATCBhjB / MQswCQYDVQQGEwJDWjEoMCYGA1UEAwwfSS5DQSBUZXN0IFB1YmxpYyBD   QS9SU0EgMTEvMjAxNTEtMCsGA1UECgwkUHJ2bsOtIGNlcnRpZmlrYcSNbsOtIGF1dG9yaXRhLCBh   LnMuMRcwFQYDVQQFEw5OVFJDWi0yNjQzOTM5NQIDAU1jMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZI   hvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTkwNjA3MTUzMjU0WjAvBgkqhkiG   9w0BCQQxIgQg3Obi7c6uoQfynW4GHXd9NRkmncvsYE1jAPUrepXO8PEwDQYJKoZIhvcNAQEBBQAE   ggEAebxo2B + ka / xHWBWniTHSMkH8wNtRN6gWpqyI / Qq8 / ZCchcT5PiUGnUFsDWXTJVaYuFG8NLOh   uRNc6pFJduPyDRCtGJxNE8o2G5mAqAvARhuY6I4DvL88 + a2Zvt1UgMyESzQqGOUT4EVCK8h + hkIy   jlBpMESiJkMO6A + gLB0hfqjS5L4oIhtqr4SLhSSmyP8h / slBABYzRB6LZipFXy5252zPcgxxb8ZE   hutzCD1K8o / qMcyXdnZT3Tm5pqKx39P3i3dLOnsus4zIDXzb2oKJwq6HfWapVngJO / bqozmhQnJj   T1uM4W / KE + sx7z / uSBOKO1DWqG48OHO4PFCRdLwAng ==   ----- END PKCS7 -----

如果将两个符号插入在线pkcs7解码器(例如,https://redkestrel.co.uk/products/decoder/),则两个符号均有效,但它们的auth_attributes内部具有不同的消息摘要八位字节,这是政府用来检查消息是否有效的部分。

我知道他们使用/弯折了 openssl smime 函数,该函数应该用于电子邮件,对于CMS,应该使用较新的 openssl cms 函数,但是CMS应该与较旧的烟雾。

我在函数中做错了什么,即同一字符串的摘要不同?

我正在使用SHA256算法(也使用),没有证书。在PKCS#7内部(也是),从而增加了身份验证时间。属性(也是)。

只有两件事是不同的。 1)他们在auth中生成了一些与SMIME相关的信息。属性,但由于我们需要相同的消息摘要,因此应将其排除在游戏之外。

2)我直接从cert获得证书。存储在C#APP的Windows中。 OpenSSL使用从商店导出的.pem。但是它们应该相等。

有什么方法可以在不链接C ++库的情况下重现OpenSSL smime函数使用的相同算法(获取相同的摘要)?

谢谢

0 个答案:

没有答案