[英]Use PrivateKey of a X509Certificate2 stored in Certificate Store and marked as non-exportable using BouncyCastle and C#
[英]How to create non-exportable private key with X509 certificate in windows key store programmatically (C#)
我正在尝试创建一个私钥并添加一个证书(自签名或从 CA 签名),我应该只能在其中导出证书并在 C# 中使私钥不可导出。也就是说,如果有人试图从certmgr导出证书,导出选项将被禁用,如下图所示-
我希望在创建它时以编程方式在 C# 中使用相同的不可导出选项。 当使用 Crypto Shell Extensions when Mark this Key is exportable未选中时安装 .pfx/.p12 文件时,私钥通常变得不可导出。
我可以成功创建密钥对并在 windows 密钥库中添加证书条目。 但是,是的,导出私钥选项始终处于启用状态,即我无法限制导出私钥。 我试过这个 -
public void init(){
AsymmetricCipherKeyPair asymmetricCipherKeyPair = GetKeyPair();
X509Name issuer = this.GenerateRelativeDistinguishedName("test org");
X509Name subject = this.GenerateRelativeDistinguishedName("test user1");
Org.BouncyCastle.X509.X509Certificate cert = GenerateCertificate(issuer, subject, asymmetricCipherKeyPair.Private, asymmetricCipherKeyPair.Public);
importSelfSignedCert(asymmetricCipherKeyPair, cert);
}
private AsymmetricCipherKeyPair GetKeyPair()
{
return new Pkcs1xHandler().GenerateKeyPair(Constants.RsaKeyLength.Length2048Bits);
}
protected X509Name GenerateRelativeDistinguishedName(String commonName)
{
IDictionary attributes = new Hashtable();
IList ordering;
attributes.Add(X509Name.CN, commonName);
ordering = new ArrayList(attributes.Keys);
return new X509Name(ordering, attributes);
}
protected void importSelfSignedCert(AsymmetricCipherKeyPair asymmetricCipherKeyPair, Org.BouncyCastle.X509.X509Certificate cert)
{
try
{
int ID =1;
AsymmetricCipherKeyPair ackp = asymmetricCipherKeyPair;
var rsaPriv = Org.BouncyCastle.Security.DotNetUtilities.ToRSA(ackp.Private as RsaPrivateCrtKeyParameters);
// Setup RSACryptoServiceProvider with "KeyContainerName" set to "KeyContainer"+ enrollmentID
var csp = new CspParameters();
csp.KeyContainerName = "TestPrivKey" + ID;
csp.Flags |= CspProviderFlags.UseMachineKeyStore;
var rsaPrivate = new RSACryptoServiceProvider(csp);
// Import private key to windows keystrore, from already generated BouncyCastle rsa privatekey
rsaPrivate.ImportParameters(rsaPriv.ExportParameters(true));
//Console.Write("rsaprivate key:" + rsaPrivate.ToXmlString(true));
System.Security.Cryptography.X509Certificates.X509Certificate2 certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2();
var flags = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet;
certificate.Import(cert.GetEncoded(), String.Empty, flags);
certificate.PrivateKey = rsaPrivate;
// opening up the windows cert store because thats where I want to save it.
System.Security.Cryptography.X509Certificates.X509Store store = new System.Security.Cryptography.X509Certificates.X509Store(System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser);
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.MaxAllowed);
store.Add(certificate);
store.Close();
rsaPrivate.PersistKeyInCsp = true; //persisting the key in container is important to retrieve the key later
///make non exporable
csp.Flags = CspProviderFlags.UseNonExportableKey;
var rsaPrivate2 = new RSACryptoServiceProvider(csp);
rsaPrivate2.ExportParameters(false); //restrict to export
rsaPrivate2.PersistKeyInCsp = true;
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Error : " + e);
Console.WriteLine(e);
Log.Print(LogLevel.High, e.ToString());
}
}
当我尝试导出证书时,我可以选择是,也导出私钥,如下图所示 -
在以编程方式创建私钥时,有什么方法可以使私钥像第一张图片一样不可导出吗? 如果有任何提示、参考或代码示例,我将不胜感激。 谢谢。
要使私钥不可导出,必须在导入密钥时另外设置CspProviderFlags.UseNonExportableKey
:
...
var csp = new CspParameters();
csp.KeyContainerName = "TestPrivKey" + ID;
csp.Flags |= CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseNonExportableKey; // Fix
var rsaPrivate = new RSACryptoServiceProvider(csp);
rsaPrivate.ImportParameters(rsaPriv.ExportParameters(true));
...
如果这样做,向导中的是,导出私钥选项将被禁用。
请注意,在发布的代码中也设置了该标志,但设置得太晚了,即在证书保存到商店之后。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.