创建密钥而不将其写入磁盘?

时间:2014-06-06 06:40:38

标签: c# security cryptography x509certificate public-key-encryption

序言

我正在深入研究.Net x509certificate2x509certificate对象,注意到默认情况下两个证书类都将私钥序列化为磁盘,因为构造函数中可以使用Persist-Key选项进行验证x509certificate2和x509certificate类的使用为CspProviderFlags设置的默认选项,不包括CspProviderFlags.CreateEphemeralKey。这可以通过任何数量的网站进行验证,这些网站显示.Net的来源以及resharper的副本,如果你自己选择这样做的话。

进一步展望,实际上这些.Net对象似乎只是一个中央旧式crypto32.dll加密上下文的包装器。令我担心的是,我更深入地查看代码,我发现它似乎明确地在磁盘文件存储中查找x509certificate2和x509certificate对象上的PublicKey字段的getter和setter中的公钥和私钥。尽管事实上,我会希望它们只存在于内存中。根据这些知识,它似乎将我的私钥存储在此存储中,即使我不希望它这样做,因为构造函数不允许您更改此选项并根据我看到的构造函数列表将其关闭看看文档;因此,如果您从PrivateKey字段设置()或get(),它实际上只是从幕后的文件存储中收集它。

我的问题原因

我认为被迫将我的私钥泄露到文件系统 - 甚至暂时 - 是一个巨大的安全问题,所以我不想这样做。我也不相信证书商店。即使你不同意我,我个人认为即使我不打算将我的私钥序列化到磁盘也是一个巨大的安全问题,所以我不想这样做。

目标

我目前的目标是简单地能够在C#中生成RSA公共和私有X509密钥,可以在Windows上使用而无需在创建过程中强制将它们写入硬盘,而我不是找到许多有效的选项,因为我能找到的所有选项似乎都有隐藏的差距或公开的问题。

目标不是永远不要将它们写入磁盘,只是不这样做,除非它使用我编写的代码并且知道它是安全的,以确保它们在静止时完全加密;也就是说,它不应该这样做,除非我在密钥本身已经完全加密后明确要求它。

目标tldr;

简而言之:我想使用C#在Windows上编写安全软件,以生成509证书,该证书不会强制我导出,导入或以其他方式将我的私钥泄露到文件系统,作为证书创建的一部分。我希望能够使用尽可能少的第三方代码在Windows上创建自己的X509Certificates。

我考虑的选项

  1. 由于上述问题,已对所述标准.Net类型进行了深入研究,发现其缺乏。我只是没有足够的权限访问内部CSP设置,因为构造函数和访问权限不会公开它们,并且默认值被用作我个人认为不安全的。
  2. Bouncy Castle库起初看起来是一个不错的选择,但它主动将我的公钥和私钥暴露给文件系统只是正常的.net类型在将它们转换为标准.Net类型时所做的事情。这些对象在幕后存储东西而不询问BC是否可以先行..
  3. 我试图找到一个crypto32.dll p-invoke选项,它允许我不对我的键进行序列化,只是发现我能找到的所有内容都完全相同,即使我不想要它们。并且在其上查找数据非常困难所以我大多只是查看源代码才发现它似乎并不像我试图不存储密钥。
  4. 尽管花了几天时间研究这个话题,但我找不到任何其他选择。甚至Stack Overflow也表示在大多数情况下使用BC或原生类型;但这并没有解决我的问题。
  5. 问题

    我如何在不执行以下任何操作的情况下最好地创建自己的X509证书,因为我觉得它们都是安全问题:

    1. 使用makecert.exe要求我允许我的进程在服务器上执行权限,以便它可以启动进程;那是一个等待发生的安全问题。更不用说,我无法审核代码,我愿意打赌它仍然将密钥存储在证书库中,即使我不希望它们存在。
    2. 使用C#/ .net x509certificate2和x509certificate对象默认通过调用证书存储区将生成的公钥序列化到磁盘,这样就不能选择;我的目标是以安全的方式做事,因此我生成的所有私钥的概念都存储在磁盘上,供任何人访问它们并不会给我留下良好的感受。并且很难在证书商店中找到数据;因此,我无法验证其安全性,必须认为它不是一个有效的选项。
    3. 使用Bouncy Castle等第三方库可以创建更新场景,并且必须信任第三方的可能性,从而创建更大的攻击面;可悲的是,他们都使用受我个人称之为“隐藏的私钥存储”的相同转换。他们试图通过使用具有此泄漏密钥问题的相同对象来尝试使用标准System.Security.Cryptography API。因此,如果一般情况下我们希望保持系统尽可能安全......那种泄漏不是一种选择。

2 个答案:

答案 0 :(得分:1)

如果不进行超低级别(或完全禁用分页),则无法保证您的私钥材料永远不会写入磁盘,因为它总是可以被分页。即使这样,在支持休眠的系统上,您的密钥也会出现在休眠文件中。

crypt32密钥存储机制使用DPAPI(用户或计算机作用域,具体取决于您在PFX中的导入标记和/或标记)来加密静态的密钥材料。因此,虽然它涉及文件系统,但它并不“存储在磁盘上,只供任何人访问它们”;除非他们像你一样运行,或者有权访问系统密钥。

答案 1 :(得分:0)

就像其他人所说的那样,如果您对此感到担忧并且不愿意信任任何人/任何外部API,那么您将不得不使用比.Net更低级的语言。 .Net是一种很棒的RAD类型语言,但是如果你不信任你运行的机器,你将需要你能达到的最低级别的环境。

C将是一个不错的选择。