使用非默认 AlgorithmIdentifier 解密 EnvelopedCms

2024-03-06

我正在尝试解密信封内容管理系统 https://msdn.microsoft.com/en-us/library/system.security.cryptography.pkcs.envelopedcms(v=vs.110).aspx使用非默认加密算法标识符 https://msdn.microsoft.com/en-us/library/248s5zhe(v=vs.110).aspx像这样:

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 或证书未放置在智能卡上,则一切正常。它本身似乎不是 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 允许我找到我的机器拥有的证书。然后,我使用从我的 store.Certificates 中找到的 X509Certificate2Collection 将集合传递到 CmsReceipientCollection。该方法执行需要128ms。哈!

 [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);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用非默认 AlgorithmIdentifier 解密 EnvelopedCms 的相关文章

  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • 使闭包捕获的变量变得易失性

    闭包捕获的变量如何与不同线程交互 在下面的示例代码中 我想将totalEvents 声明为易失性的 但C 不允许这样做 是的 我知道这是错误的代码 这只是一个例子 private void WaitFor10Events volatile
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 如何将图像和 POST 数据上传到 Azure 移动服务 ApiController 终结点?

    我正在尝试上传图片and POST表单数据 尽管理想情况下我希望它是json 到我的端点Azure 移动服务应用 我有ApiController method HttpPost Route api upload databaseId sea
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • Json.NET - 反序列化接口属性引发错误“类型是接口或抽象类,无法实例化”

    我有一个类 其属性是接口 public class Foo public int Number get set public ISomething Thing get set 尝试反序列化Foo使用 Json NET 的类给我一条错误消息
  • Cython 和类的构造函数

    我对 Cython 使用默认构造函数有疑问 我的 C 类 Node 如下 Node h class Node public Node std cerr lt lt calling no arg constructor lt lt std e
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 在 ASP.NET Core 3.1 中使用包含“System.Web.HttpContext”的旧项目

    我们有一些用 Net Framework编写的遗留项目 应该由由ASP NET Core3 1编写的API项目使用 问题是这些遗留项目正在使用 System Web HttpContext 您知道它不再存在于 net core 中 现在我们
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 将 xml 反序列化为类,list<> 出现问题

    我有以下 XML
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐