C# 是否可能使用AES和RSA加密(PKCS#1 v1.5填充而不是v2(OAEP)填充)的信封CMS?

C# 是否可能使用AES和RSA加密(PKCS#1 v1.5填充而不是v2(OAEP)填充)的信封CMS?,c#,encryption,cryptography,aes,rsa,C#,Encryption,Cryptography,Aes,Rsa,我一直在使用.NET进行加密。到目前为止,我将3DES(Oid 1.2.840.113549.3.7)与RSA加密(Oid 1.2.840.113549.1.1.1,RSAES-PKCS1-v1_5)结合使用。虽然第一个现在必须被AES(Oid 2.16.840.1.101.3.4.1.42)取代,但我仍然必须使用RSAES加密,而不是RSAES-OAEP 如果我只是将一个附加参数传递给我正在调用的EnvelopedCMS构造函数,我可以从3DES切换到AES: ContentInfo

我一直在使用.NET进行加密。到目前为止,我将3DES(Oid 1.2.840.113549.3.7)与RSA加密(Oid 1.2.840.113549.1.1.1,RSAES-PKCS1-v1_5)结合使用。虽然第一个现在必须被AES(Oid 2.16.840.1.101.3.4.1.42)取代,但我仍然必须使用RSAES加密,而不是RSAES-OAEP

如果我只是将一个附加参数传递给我正在调用的EnvelopedCMS构造函数,我可以从3DES切换到AES:

    ContentInfo plainContent = new ContentInfo(new Oid("1.2.840.113549.1.7.1"), data);

    EnvelopedCms encryptedMessage = new EnvelopedCms(plainContent); // using 3DES
    // EnvelopedCms encryptedMessage = new EnvelopedCms(plainContent, new AlgorithmIdentifier(new Oid("2.16.840.1.101.3.4.1.42")));  // for AES (id-aes256-CBC)

    CmsRecipient recipient = new CmsRecipient(cert);
    encryptedMessage.Encrypt(recipient);

    byte[] encryptedBytes = encryptedMessage.Encode();
到目前为止还可以。不幸的是,有些收件人无法解密我的邮件,尽管他们能够解密AES。查看ASN.1结构告诉我,不仅3DES变为AES,而且RSAES加密(1.2.840.113549.1.1.1)也被RSAES-OAEP(1.2.840.113549.1.7)所取代。我是否可以强制将RSAES-PKCS1-v1_5与EnvelopedCMS一起使用?或者,在切换3DES->AES时,您是否发现了另一个问题


编辑:如果我不能很容易地将填充更改为v1.5,我还有什么其他选项?手动调用CryptoServiceProviders并自行构建PKCS#7信封?还有更优雅的方法吗?

基于Windows CAPI CryptMsg*函数构建的.NET Framework Enveloped CMS。CryptMsgPentoencode支持两种对收件人进行编码的方法,其中一种是有条件编译的(尽管我无法确定它何时不可用;我怀疑这是Win9x vs NT4/WinXP compat的问题)

一时兴起,我想看看有什么可以翻转它来使用另一个代码路径,以及这是否会改变你的结果。事实证明,是的,在内部使用“useCms”会导致收件人加密算法为1.2.840.113549.1.1.1

选项1)使用SubjectKeyIdentifier标识 如果您正在与另一个系统进行互操作(如此处所示),请确保证书具有明确的SubjectKeyIdentifier扩展名,然后再使用此标识表单。如果没有显式值,NET/Windows将组成隐式值,并且在这种情况下,并非所有CMS实现都与收件人证书匹配(例如OpenSSL)

您可以通过将CMS用户更改为

CmsRecipient recipient = new CmsRecipient(SubjectIdentifierType.SubjectKeyIdentifier, cert);
选项2)添加未受保护的属性 EnvelopedCms允许在未加密的消息中添加其他元数据。指定这些值中的任何一个都会使加密机/编码器使用备用代码路径

在调用Encrypt add之前

// Pkcs9DocumentName requires a non-empty string.
// You can use any AsnEncodedData value, though.
encryptedMessage.UnprotectedAttributes.Add(new Pkcs9DocumentName("a"));

他们每个人都在本地测试中工作。

我在谷歌上搜索了不少,但找不到多少。请注意,PKCS#1 v1.5有一些您可能希望避免的重要漏洞(在RSA v2.1 RFC中解释)。它可能是安全的,但它确实需要相当多的检查才能安全。OAEP确实在协议的安全性方面更有意义。据我所知,我更喜欢OAEP。不幸的是,我必须遵守既定的协议。由于我的消息在chance 3des->aes之后无法解密,因此与给定规则相比,我的系统中唯一的区别是使用OAEP而不是RSA加密。还有其他实现方法吗(最好只使用.NET类)?据我目前所知,BouncyCastle功能非常强大(尽管没有为C#编写很好的文档)。有什么想法可以在那里实现解决方案吗?我在为Bouncy Castle实现解决方案时不会遇到太多问题,因为它会浮回到我的脑海中。它当然是可配置的,如果不是,至少很容易获得源代码。不幸的是,我不知道一个解决方案,虽然我的头顶。我当然会认为这是解决这个特殊问题的好人选。在不太可能的情况下,它不支持解决方案,您可以简单地修复并重新编译它。感谢您的考虑。由于最后期限给这个问题带来了很大的压力,我现在选择了一个商业图书馆()为这个特定的问题提供一个现成的解决方案。希望这一问题现在能够得到解决。很抱歉,最终未能仅使用.NET.Hi提供一个平滑的解决方案,非常感谢您的回答!您是否理解为什么添加未受保护的属性或使用SubjectIdentifierType.SubjectKeyIdentifier会将KEA更改为RSA(1.2.840.113549.1.1.1)?@Pawellsinsikowski这两个功能在CMS规范的更高版本中出现,因此需要对Windows进行更新的API调用。旧的表单只接受一个证书并选择OAEP(因为它在某些攻击模型下具有更好的安全性)。较新的表单将加密算法作为一个输入,.NET使用证书的公钥算法标识符(RSA)填充,而不将RSA提升到RSA_OAEP。useCms==false是较新的版本吗?@Pawellsnikowski No,
useCms==true
意味着它使用CMSG_encoded_INFO()的
rgCmsRecipients
字段,而不是
rgpRecipents
。但这显著地改变了.NET和Windows之间的交互。我理解其中的机制(我想),但我不理解其中的原因。为什么有两种加密信封cms的方法?我是否正确理解未受保护的属性是“新”API?如果是,为什么使用它会强制AES与旧密钥交换(RSA而不是RSAES-OAEP)一起使用