![]() |
1
53
主要是,今天必须如此复杂,因为昨天如此复杂,没有人想出更简单的办法。 我不能在这里提出一个线性的叙述,所以请忍受来回编织的要求。 什么是PFX/PKCS#12文件?虽然我不能完全说明PFX的起源,但在Windows函数的名称中有一条线索可以用来读写它们: PFXImportCertStore 和 PFXExportCertStore . 它们包含许多单独的实体(证书、私钥和其他东西),可以使用属性标识符来相互关联。它们似乎被设计成一个用于整个证书存储的导出/导入机制,就像所有CurrentUser\My一样。但是由于有一种存储是“内存存储”(一个任意的集合),.NET导入/导出是有意义的,但是(在.NET之前)会出现一些复杂的情况。 Windows支持许多不同的位置来存放私钥,但对于传统的crypto API,它们可以归结为4部分寻址方案:
这简化为CNG的三部分方案:
CAPI和CNG都支持直接与命名密钥交互。所以您创建了一个名为“EmailDecryption”的密钥。系统上的另一个用户创建了一个同名的密钥。这样行吗?嗯,可能吧。所以,哈扎,是的!单独的键,因为它们被保存在与生成它们的用户相关的上下文中。
我将继续在这里说,我听说直接使用命名键现在是不鼓励的;CAPI/CNG团队更喜欢使用GUID命名的密钥,并且您可以通过cert存储与它们交互。但这是进化的一部分。 导入PFX做什么?CryptImportKey BCryptImportKey ,取决于它认为需要什么)。然后,对于它导入的每个密钥,它找到(通过PFX中的属性值)匹配的证书,并在cert store表示上为“this is my 4-part identifier”设置一个属性(CNG keys只是将第4部分设置为0);这实际上是cert对其私钥的全部了解。 (PFX是一种非常复杂的文件格式,只要没有“奇怪的部分”被利用,这种描述是正确的) 关键生命周期
因此,当PFX导入它们时,它们将永远存活。如果您正在导入到CurrentUser\My,这是有意义的。如果你在做一些短暂的事情,那就没什么意义了。 .NET颠倒了关系/使之“太简单”Windows的设计(主要)是与证书存储交互,并从证书存储获得证书。NET后来出现了,并且(我们假设,基于看到应用程序真正在做什么)将证书作为顶级对象,而存储则是次要的。
哦,但是MMC证书管理器说它可以导出带有私钥的证书(到PFX中),为什么除了“just a cert”格式之外,cert构造函数不能接受这些字节?好吧,现在可以了。 调和寿命您打开了一些字节作为X509Certificate/X509Certificate2。它是一个带有“无密码”的PFX(通过各种可能是真的方式)。你看它是错的,你让证书去垃圾收集器。私钥会永远存在,所以硬盘会慢慢填满,密钥存储访问也会越来越慢。然后你生气了,重新格式化你的电脑。 这看起来很糟糕,所以.NET所做的是当证书的(一个字段)被垃圾收集(实际上是最终确定)时,它告诉CAPI(或CNG)删除密钥。现在一切正常了,对吧?好吧,只要程序没有异常终止。
输入
|