【问题标题】:Bouncycastle write cms MIME header in ascii/binary formatBouncycastle 以 ascii/二进制格式写入 cms MIME 标头
【发布时间】:2020-10-06 11:34:49
【问题描述】:

我使用 bouncycastle c# 生成 cms 签名数据文件,我的 openSsl 命令如下

openssl cms -sign -in data.txt -binary -signer selfsigned.crt -inkey keypair.pem -out data.signed -keyopt rsa_padding_mode:pss 

输出文件形式为openssl

MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha-256"; boundary="----DE5BACF44AD3EE95D349BA916BEEB444"

This is an S/MIME signed message

------DE5BACF44AD3EE95D349BA916BEEB444
Data HERE
------DE5BACF44AD3EE95D349BA916BEEB444
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"

SOME BASE 64 DATA
------DE5BACF44AD3EE95D349BA916BEEB444--

===============================================

BouncyCastle 的输出不一样,即用 ascii 格式编写的标头,类似的东西

0€  *†H†÷
 €0€10
    `†He 0€ *†H†÷
 €$€‚

Data HERE

 €0€10
    `†He 0€ *†H†÷
 €$€‚ €0€10
    `†He 0€ *†H†÷
 €$€‚ €0€10
    `†He 0€ *†H†÷
 €$€‚ €0€10
    `†He 0€ *†H†÷
 €$€‚

如何获得与openssl一样的标题

cms 标志的 BouncyCastle 代码

void Sign(byte[] data, byte[] signCert, byte[] privateKey){
            X509CertificateParser parser = new X509CertificateParser();
            X509Certificate certificate = parser.ReadCertificate(signCert);
            var reader = new StreamReader(new MemoryStream(privateKey), Encoding.Default);
            AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
            CmsSignedDataGenerator generator = new CmsSignedDataGenerator();
            generator.AddSigner(keyPair.Private, certificate, CmsSignedGenerator.EncryptionRsaPss, 
            CmsSignedGenerator.DigestSha256);
            List<X509Certificate> certList = new List<X509Certificate>();
            certList.Add(certificate);
            CmsSignedData signedData = generator.Generate(CmsSignedGenerator.Data, new 
            CmsProcessableByteArray(data), true);
            File.WriteAllBytes(@"c:\data.txt.signed", signedData.GetEncoded());
    }

有什么想法吗?

【问题讨论】:

    标签: openssl bouncycastle


    【解决方案1】:

    BouncyCastle 不会生成这些标题。您需要自己完成这项工作,或者使用像 MimeKit 这样的库来为您完成这项工作。

    【讨论】:

    • 我能够生成签名文件,但我有两个问题。首先,我想将 MimeMessage Body 设置为字节数组,当我尝试使用 openssl 验证生成输出时,它给了我失败的原因 30080:error:2E09A09E:CMSroutines:CMS_SignerInfo_verify_content:verification failure:crypto\cms\cms_sd.c :848: 30080:error:2E09D06D:CMS 例程:CMS_verify:内容验证错误:crypto\cms\cms_smime.c:393:
    • 我不知道你在做什么,所以我不能告诉你你做错了什么。
    • 如何将 mimemessage body 设置为字节数组?
    • 创建一个 MimePart 并将内容设置为带有字节数组数据的 MemoryStream。然后将 MimePart 设置为消息正文。
    • MimePart mimePart = new MimePart(); mimePart.Content.Stream.Write(数据); MimeMessage 消息 = 新 MimeMessage { 正文 = mimePart };我这样做了,但没有工作,或者我可能遗漏了什么?
    【解决方案2】:

    在尝试了不同的库后,但没有成功,我想出了一种使用 BouncyCastle 实现此目的的方法,我只需要手动添加标题并修复代码即可实现它

    public byte[] Sign(byte[] data, byte[] signCert, byte[] privateKey)
            {
                
                X509CertificateParser parser = new X509CertificateParser();
                X509Certificate certificate = parser.ReadCertificate(signCert);
                var reader = new StreamReader(new MemoryStream(privateKey), Encoding.Default);
                AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
    
                CmsSignedDataGenerator generator = new CmsSignedDataGenerator();
    
                generator.AddSigner(keyPair.Private, certificate, CmsSignedGenerator.EncryptionRsaPss, CmsSignedGenerator.DigestSha256);
    
                List<X509Certificate> certList = new List<X509Certificate>
                {
                    certificate
                };
                IX509Store iX509Store = X509StoreFactory.Create("Certificate/Collection", new X509CollectionStoreParameters(certList));
                generator.AddCertificates(iX509Store);
    
                CmsSignedData signedData = generator.Generate(CmsSignedGenerator.Data, new CmsProcessableByteArray(data), true);
    
                var signedBase64Encoded = Base64.Encode(signedData.GetEncoded());
                var signedString = Encoding.UTF8.GetString(signedBase64Encoded);
                signedString = "MIME-Version: 1.0\n"
                                + "Content-Disposition: attachment; filename=\"smime.p7m\"\n"
                                + "Content-Type: application/pkcs7-mime; smime-type=signed-data; name=\"smime.p7m\"\n"
                                + "Content-Transfer-Encoding: base64\n\n"
                                + Regex.Replace(signedString, "(.{" + 64 + "})", "$1" + Environment.NewLine);
    
                return Encoding.UTF8.GetBytes(signedString);
            }  
    

    【讨论】:

      猜你喜欢
      • 2017-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-07
      • 1970-01-01
      相关资源
      最近更新 更多