static void SetCngPrivateKeySecurity(SafeCertContextHandle certificate, ICollection <PrivateKeyAccessRule> accessRules) { using (var key = CertificatePal.GetCngPrivateKey(certificate)) { var security = GetCngPrivateKeySecurity(certificate); foreach (var cryptoKeyAccessRule in accessRules.Select(r => r.ToCryptoKeyAccessRule())) { security.AddAccessRule(cryptoKeyAccessRule); } var securityDescriptorBytes = security.GetSecurityDescriptorBinaryForm(); var gcHandle = GCHandle.Alloc(securityDescriptorBytes, GCHandleType.Pinned); var errorCode = NCryptSetProperty(key, NCryptProperties.SecurityDescriptor, gcHandle.AddrOfPinnedObject(), securityDescriptorBytes.Length, (int)NCryptFlags.Silent | (int)SecurityDesciptorParts.DACL_SECURITY_INFORMATION); gcHandle.Free(); if (errorCode != 0) { throw new CryptographicException(errorCode); } } }
static CryptoKeySecurity GetCngPrivateKeySecurity(SafeCertContextHandle certificate) { using (var key = CertificatePal.GetCngPrivateKey(certificate)) { var security = new CryptoKeySecurity(); security.SetSecurityDescriptorBinaryForm(CertificatePal.GetCngPrivateKeySecurity(key), AccessControlSections.Access); return(security); } }
/// <summary> /// Unlike X509Store.Remove() this function also cleans up private-keys /// </summary> public static void RemoveCertificateFromStore(string thumbprint, StoreLocation storeLocation, string storeName) { var store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadWrite); var found = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); if (found.Count == 0) { return; } var certificate = found[0]; var certificateHandle = new SafeCertContextHandle(found[0].Handle, false); // If the certificate has a private-key, remove it if (certificateHandle.HasPrivateKey()) { var keyProvInfo = certificateHandle.GetCertificateProperty <KeyProviderInfo>(CertificateProperty.KeyProviderInfo); // If it is a CNG key if (keyProvInfo.dwProvType == 0) { try { var key = CertificatePal.GetCngPrivateKey(certificateHandle); CertificatePal.DeleteCngKey(key); } catch (Exception ex) { throw new Exception("Exception while deleting CNG private key", ex); } } else // CAPI key { try { IntPtr providerHandle; var acquireContextFlags = CryptAcquireContextFlags.Delete | CryptAcquireContextFlags.Silent; if (storeLocation == StoreLocation.LocalMachine) { acquireContextFlags = acquireContextFlags | CryptAcquireContextFlags.MachineKeySet; } var success = Native.CryptAcquireContext(out providerHandle, keyProvInfo.pwszContainerName, keyProvInfo.pwszProvName, keyProvInfo.dwProvType, acquireContextFlags); if (!success) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } catch (Exception ex) { // Swallow keyset does not exist if (!(ex is CryptographicException && ex.Message.Contains("Keyset does not exist"))) { throw new Exception("Exception while deleting CAPI private key", ex); } } } } store.Remove(certificate); store.Close(); }