[英]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.