Я пытаюсь прочитать закрытый ключ сертификата, который был предоставлен мне сторонним поставщиком услуг, поэтому я могу использовать его для шифрования некоторых XML, прежде чем отправлять их им по проводу. Я делаю это программно в С#, но я думаю, что это проблема с разрешениями или неправильной конфигурацией, поэтому я сосредоточу внимание на фактах, которые кажутся наиболее важными:
- Я не думаю, что эта проблема связана с кодом; мой код работает на других компьютерах, и проблема влияет на образец кода из Microsoft.
- Сертификат был предоставлен как файл PFX и предназначен только для тестирования, поэтому он также включает фиктивный центр сертификации.
- Используя MMC.exe, я могу импортировать сертификат в личное хранилище для локального компьютера, прежде чем предоставлять разрешения на закрытый ключ всем соответствующим учетным записям и перетащить центр сертификации в доверенные корневые центры сертификации.
- Используя С#, я могу загрузить сертификат (идентифицированный его отпечатком) и убедиться, что он имеет закрытый ключ, используя
X509Certificate2.HasPrivateKey
. Однако попытка прочитать ключ вызывает ошибку. В .NET aCryptographicException
вызывается с сообщением "Недопустимый тип провайдера" при попытке получить доступ к свойствуX509Certificate2.PrivateKey
. В Win32 вызов методаCryptAcquireCertificatePrivateKey
возвращает эквивалентный HRESULT,NTE_BAD_PROV_TYPE
. - Это то же самое исключение, которое также возникает при использовании двух собственных образцов кода Microsoft для чтения закрытого ключа сертификата.
- Установка того же сертификата в эквивалентном хранилище для текущего пользователя вместо локального компьютера позволяет успешно загружать закрытый ключ.
- Я нахожусь в Windows 8.1 с правами локального администратора, и я попытался запустить свой код как в нормальном, так и в повышенном режиме. Коллегам Windows 7 и Windows 8 удалось загрузить ключ из локального хранилища компьютеров для того же сертификата.
- Я могу успешно прочитать закрытый ключ самозаверяющего сертификата IIS, который находится в том же хранилище.
- Я уже ориентируюсь на .NET 4.5 (эта ошибка сообщалась с некоторыми более старыми версиями фреймворка).
- Я не думаю, что это проблема с шаблонами сертификатов, потому что я ожидаю, что это повлияет как на локальную машину, так и на магазины текущего пользователя одинаково?
В отличие от моих коллег, я сделал несколько предыдущих попыток удалить и переустановить сертификат различными способами, в том числе через диспетчер IIS, а также старый сертификат того же эмитента. Я не вижу никаких следов старых или дубликатов сертификатов в MMC. Тем не менее, у меня есть много файлов личных ключей одинакового размера, которые, основываясь на времени последней записи, должны были остаться после моих различных попыток установки. Они находятся в следующих местах для локального компьютера и текущих пользовательских хранилищ соответственно:
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
c:\Users\\AppData\Роуминг\Microsoft\Crypto\RSA\S-1-5-21- [остальные идентификаторы пользователя]
Итак, кто-нибудь может посоветовать:
- Рекомендуется удалить сертификат с помощью MMC, удалить все те файлы, которые выглядят как потерянные частные ключи, а затем повторно установить сертификат и повторить попытку?
- Есть ли другие файлы, которые я должен удалить вручную?
- Что-нибудь еще я должен попробовать?
UPDATE - добавлен образец кода, показывающий попытку прочитать закрытый ключ:
static void Main()
{
// Exception occurs when trying to read the private key after loading certificate from here:
X509Store store = new X509Store("MY", StoreLocation.LocalMachine);
// Exception does not occur if certificate was installed to, and loaded from, here:
//X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Test Certificate Select", "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.MultiSelection);
Console.WriteLine("Number of certificates: {0}{1}", scollection.Count, Environment.NewLine);
foreach (X509Certificate2 x509 in scollection)
{
try
{
Console.WriteLine("Private Key: {0}", x509.HasPrivateKey ? x509.PrivateKey.ToXmlString(false) : "[N/A]");
x509.Reset();
}
catch (CryptographicException ex)
{
Console.WriteLine(ex.Message);
}
}
store.Close();
Console.ReadLine();
}