- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试解密 EnvelopedCms使用非默认 AlgorithmIdentifier 加密的像这样:
ContentInfo contentInfo = new ContentInfo(data);
EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo, new AlgorithmIdentifier(new System.Security.Cryptography.Oid("2.16.840.1.101.3.4.1.42")));
CmsRecipientCollection recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, certificates);
envelopedCms.Encrypt(recipients);
byte[] encryptedData = envelopedCms.Encode();
加密按预期工作。现在,当我尝试使用如下内容解密 envelopedCms
时:
EnvelopedCms envelopedCms = new EnvelopedCms();
envelopedCms.Decode(encryptedData );
envelopedCms.Decrypt(certificates);
byte[] decryptedData = envelopedCms.ContentInfo.Content;
我注意到 a.) 访问证书需要很长时间(比使用默认 AlgorithmIdentifier 时更长)和 b.) 我收到此错误消息:
System.Security.Cryptography.CryptographicException: Access was denied because of a security violation.
从失败的来源来看,这可能不是问题所在。任何人都可以[使用智能卡]获得上面的解密代码吗?
//编辑1请注意,仅当使用的证书位于智能卡上并且指定了默认算法标识符 (3DES) 以外的 AlgorithmIdentifier 时,才会出现此问题,如示例代码中所示。如果使用默认的 AlgorithmIdentifier 或证书未放置在智能卡上,则一切正常。它本身看起来不像是 SC 问题,因为它使用默认的 AlgorithmIdentifier。导致问题的原因是 SC 和 AES AlgorithmIdentifier 的组合,但我找不到有效的解决方案。
//编辑2演示该问题的完整示例,阅读评论了解详情:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Security.Cryptography.Pkcs;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
// Select the (smartcard) certificate to use it for encryption
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Certificate Select", "Select your smartcard certificate", X509SelectionFlag.MultiSelection);
// Output which certificate will be used
Console.WriteLine("Using Certificate:");
int i = 0;
foreach (X509Certificate2 x509 in scollection)
{
byte[] rawdata = x509.RawData;
Console.WriteLine("---------------------------------------------------------------------");
Console.WriteLine("1.\tFull DN: {0}", x509.Subject);
Console.WriteLine("\tThumbprint: {0}", x509.Thumbprint);
Console.WriteLine("---------------------------------------------------------------------");
i++;
}
store.Close();
// Wait
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
// Create data for encryption
string message = "THIS IS OUR SECRET MESSAGE";
byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Encrypt
Console.WriteLine("Encrypting message...");
// ContentInfo contentInfo = new ContentInfo(data); // will use default ContentInfo Oid, which is "DATA"
// Explicitly use ContentInfo Oid 1.2.840.113549.1.7.1, "DATA", which is the default.
ContentInfo contentInfo = new ContentInfo(new System.Security.Cryptography.Oid("1.2.840.113549.1.7.1"), data);
// If using OID 1.2.840.113549.3.7 (the default one used if empty constructor is used) or 1.2.840.113549.1.9.16.3.6 everything works
// If using OID 2.16.840.1.101.3.4.1.42 (AES CBC) it breaks
AlgorithmIdentifier encryptionAlgorithm = new AlgorithmIdentifier(new System.Security.Cryptography.Oid("1.2.840.113549.3.7"));
// EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo); // this will use default encryption algorithm (3DES)
EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo, encryptionAlgorithm);
Console.WriteLine("Encyption Algorithm:" + envelopedCms.ContentEncryptionAlgorithm.Oid.FriendlyName);
Console.WriteLine("Encyption Algorithm:" + envelopedCms.ContentEncryptionAlgorithm.Oid.Value);
CmsRecipientCollection recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, scollection);
/*Console.WriteLine("Receipientinfo count: " + encryptionEnvelopedCms.RecipientInfos.Count.ToString());
foreach (var i in encryptionEnvelopedCms.RecipientInfos)
{
Console.Write("RecipientInfo Encryption Oid: " + i.KeyEncryptionAlgorithm.Oid);
}
*/
envelopedCms.Encrypt(recipients);
byte[] encryptedData = envelopedCms.Encode();
Console.WriteLine("Message encrypted!");
// Decrypt
envelopedCms.Decode(encryptedData);
Console.WriteLine("Decryption Algorithm:" + envelopedCms.ContentEncryptionAlgorithm.Oid.FriendlyName);
Console.WriteLine("Decryption Algorithm:" + envelopedCms.ContentEncryptionAlgorithm.Oid.Value);
// Next line will fail if both conditions are true:
// 1. A non-default AlgorithmIdentifier was used for encryption, in our case AES
// 2. The private key required for decryption is placed on a smartcard that requires a manual action, such as entering a PIN code, before releasing the private key
// Note that everything works just fine when the default AlgorithmIdentifier is used (3DES) or the private key is available in the X509Store
envelopedCms.Decrypt(scollection);
byte[] decryptedData = envelopedCms.ContentInfo.Content;
Console.WriteLine("Message decrypted!");
Console.WriteLine("Decrypted message: " + System.Text.Encoding.ASCII.GetString(decryptedData));
Console.WriteLine("Press any key to exit.");
Console.ReadKey(true);
}
}
}
最佳答案
虽然我的回答可能会导致一些不完整的切线,但我相信它会让您得到与我得出的相同的断言。事实上,我使用 X509Store 允许我找到我的机器拥有的证书。然后,我将集合传递到 CmsReceipientCollection 中,其中包含从我的 store.Certificates 中找到的 X509Certificate2Collection。这个方法需要 128ms 来执行。 HTH!
[TestMethod]
public void TestEnvelopedCMS()
{
X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
byte[] data = new byte[256];
//lets change data before we encrypt
data[2] = 1;
ContentInfo contentInfo = new ContentInfo(data);
EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo, new AlgorithmIdentifier(new System.Security.Cryptography.Oid("2.16.840.1.101.3.4.1.42")));
CmsRecipientCollection recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, fcollection);
envelopedCms.Encrypt(recipients);
byte[] encryptedData = envelopedCms.Encode();
//lets decrypt now
envelopedCms.Decode(encryptedData);
envelopedCms.Decrypt(fcollection);
byte[] decryptedData = envelopedCms.ContentInfo.Content;
//grab index from byte[]
var item = decryptedData.Skip(2).Take(1).FirstOrDefault();
var item2 = data.Skip(2).Take(1).FirstOrDefault();
Assert.IsTrue(item == item2);
}
关于c# - 使用非默认 AlgorithmIdentifier 解密 EnvelopedCms,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44776088/
我正在尝试解密 EnvelopedCms使用非默认 AlgorithmIdentifier 加密的像这样: ContentInfo contentInfo = new ContentInfo(data
几天来我一直在努力解决这个问题,RFC 2315 有点难以理解。 我正在尝试实现我自己的 EnvelopedCms.Decrypt() 版本,以便我可以使用 Azure Key Vault 的证书操作
我一直在将 .NET 用于加密目的。到目前为止,我将 3DES (Oid 1.2.840.113549.3.7) 与 rsaEncryption (Oid 1.2.840.113549.1.1.1,
我是一名优秀的程序员,十分优秀!