首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在.NET 4中,在根目录中插入证书(带有私有密钥),LocalMachine证书存储失败

在.NET 4中,在根目录中插入证书(带有私有密钥),LocalMachine证书存储失败
EN

Stack Overflow用户
提问于 2010-09-02 17:07:58
回答 6查看 24.1K关注 0票数 18

我在本地计算机的根证书存储中插入带有privatekey的新CA证书时遇到问题。

这就是发生的事情:

代码语言:javascript
复制
//This doesn't help either.
new StorePermission (PermissionState.Unrestricted) { Flags = StorePermissionFlags.AddToStore }.Assert();
var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
privkey.PersistKeyInCsp = true;
//This shouldn't be necessary doesn't make a difference what so ever.
RSACryptoServiceProvider.UseMachineKeyStore = true;
cert.PrivateKey = privkey;
store.Open (OpenFlags.MaxAllowed);
store.Add (cert);
store.Close ();

插入证书后,一切看起来都很棒:(请参见!)

注意: is说它有一个私有密钥。

所以你会说你可以用FindPrivateKey找到它

代码语言:javascript
复制
C:\Users\Administrator\Desktop>FindPrivateKey.exe Root LocalMachine -t "54 11 b1 f4 31 99 19 d3 5a f0 5f 01 95 fc aa 6f 71 12 13 eb"
FindPrivateKey failed for the following reason:
Unable to obtain private key file name

Use /? option for help 

很可爱..。但这是错误的!!(2只愚蠢的狗参考)

证书导出对话框给出了一条非常好的消息:

在使用以下代码片段模拟管理员时运行此代码:click here

我只想知道为什么?

(在Windows Server2008 R2和Windows7上测试)

我会被诅咒的!

当我把它编译成v3.5时,它就能工作了!

该怎么办呢?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-06-23 22:20:20

我遇到了完全相同的问题,解决方案变得非常简单。我要做的就是通过

代码语言:javascript
复制
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet

到X509Certificate2的ctor。现在您正在使用DotNetUtilities将bouncycastle证书转换为.net证书,但是helper方法使用DefaultKeySet (而不是MachineKeySet + PersistKeySet )创建.net证书。

私钥的排列方式如下:

代码语言:javascript
复制
var cspParams = new CspParameters
{
      KeyContainerName = Guid.NewGuid().ToString(),
      KeyNumber = (int)KeyNumber.Exchange,
      Flags = CspProviderFlags.UseMachineKeyStore
};

var rsaProvider = new RSACryptoServiceProvider(cspParams);

我希望这能帮到你。

票数 11
EN

Stack Overflow用户

发布于 2010-09-05 19:15:38

在我看来,您应该以另一种方式导入密钥。有关示例,请参阅http://support.microsoft.com/kb/950090

此外,我发现在UseMachineKeyStore中保存私钥是不好的。在大多数情况下,您需要导入证书与私钥在我的存储中的一些用户,并在根只导入证书没有私钥。

如果你确实需要将私钥保存在机器密钥库中,那么你至少应该保护密钥只供某些选定的用户读取,而不是每个人都可以读取。密钥容器只是文件系统中的一个文件(请参阅目录“%ALLUSERSPROFILE%\Microsoft\Crypto\Keys”中的文件),该文件与NTFS中的其他文件一样具有安全描述符。要更改文件的安全描述符,可以使用CspKeyContainerInfo.CryptoKeySecurity属性和AddAccessRuleRemoveAccessRule等。

更新了:首先,很抱歉回答了这么长的问题。

我可以把your program code分成两部分。在第一部分中,您将生成一个可用作CA证书的自签名证书,并将其保存为rootcert.pfx文件。在第二部分中,您将导入证书,但不使用rootcert.pfx,而是使用由先前创建的密钥的属性填充的RSACryptoServiceProvider

我建议将代码的第二部分替换为更标准、更简单的代码:使用来自 rootcert.pfx 的私钥导入证书,如 中所述。它工作得非常好。

我不使用自己的BouncyCastle,所以我不能注释您代码的第一部分,但一般来说,您在代码中所做的事情也可以与Windows SDK中的MakeCert.exe实用工具相关。你可以像下面这样做

代码语言:javascript
复制
MakeCert.exe -pe -ss MY -a sha1 -cy authority -len 2048 -m 120 -r -# 1
             -n "CN=Some Root CA, C=NL, OU=BleedingEdge, ST=Somewhere, L=Somelane"

然后,您可以根据证书管理单元(用于mmc.exe)导出带有或不带有私钥的证书。在上面的例子中,我没有限制CA用于一些特殊的EKU,所以你可以不受任何限制地使用它,但是如果你确实需要这些限制,你可以只向MakeCert.exe添加额外的参数。您还可以使用MakeCert.exe创建用CA证书签名的其他证书。所以你只能就MakeCert.exe做一个小型的公钥基础设施。

在我看来,创建证书实际上是代码的一个单独部分。你的主要问题在第二部分。

如果你想导入CA证书,你应该考虑一些重要的事情:

  • 您应该将其导入组织中每台(或多台)计算机上的Root中或localMachine中的AuthRoot中,但是应该导入不带私钥的证书。您可以针对以下

执行此操作

CertMgr.exe -add -c CA.cer -s -r localMachine AuthRoot

  • 您应该使用私钥将CA证书导入到one计算机上的计算机上,并仅将导入给将颁发其他证书(将使用CA的私钥签署新证书)的用户。一种用于导入CurrentUser.的My证书存储中的证书因此,计算机上的代码可能看起来像

如下所示:

代码语言:javascript
复制
// import PFX
X509Certificate2 cert = new X509Certificate2 (@"c:\Oleg\rootcert.pfx", "password",
    X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
// save certificate and private key
X509Store storeMy = new X509Store (StoreName.My, StoreLocation.CurrentUser);
storeMy.Open (OpenFlags.ReadWrite);
storeMy.Add (cert);

// get certificate without private key
// one can import certificate from rootcert.cer instead
byte[] certBlobWithoutPrivateKey = cert.Export (X509ContentType.Cert);
// save pure certificate in Root of the local machine
X509Certificate2 certWithoutPrivateKey = new X509Certificate2 (certBlobWithoutPrivateKey);
X509Store storeRoot = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
storeRoot.Open (OpenFlags.ReadWrite);
storeRoot.Add (certWithoutPrivateKey);

如果您将StoreName.MyStoreLocation.CurrentUser更改为另一个值,代码将会正常工作,但我不建议您这样做。

一般而言,在.NET代码中导入证书看起来有点奇怪,并且没有显示将在幕后完成的工作。Windows只知道将私钥(与密钥对完全相同)保存在何处的Key Containers,以及将保存证书的CSP和Certificate Stores (有关存储位置的信息,请参阅http://msdn.microsoft.com/en-us/library/bb204781.aspx )。为了能够在证书库中保存有关密钥容器的信息,微软引入了名为Certificate Extended Properties的证书。如果在X509Certificate2的.NET属性中使用,如ThumbprintFriendlyNameHasPrivateKeyArchived等,则使用证书的扩展属性。所以我建议您导入CA证书两次。一次是在RootAuthRoot 中,不使用设置CERT_KEY_PROV_INFO_PROP_ID Certificate Extended Properties,另一次是在My存储中使用设置私钥容器的位置信息(CERT_KEY_PROV_INFO_PROP_ID)。此外,你可以考虑在使用后直接删除私钥,只有当你真的需要使用它时才导入它,并且不永久持有它。所有这些对于拥有更好的安全性都很重要。

票数 10
EN

Stack Overflow用户

发布于 2011-02-12 00:45:06

我遇到过这个问题,似乎即使是运行FindPrivateKey工具的用户也没有访问密钥的权限,因此您会收到"Unable to obtain private key file name“消息。您可以将该工具作为LocalSystem进程运行。

更多信息请点击此处:

http://www.itsolutionbraindumps.com/2011/02/finding-private-key-for-your.html

Dinko

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3625624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档