"Возникла внутренняя ошибка." при загрузке файла pfx с помощью X509Certificate2

79

Я пытаюсь использовать самозаверяющий сертификат (c #):

X509Certificate2 cert = new X509Certificate2(
    Server.MapPath("~/App_Data/myhost.pfx"), "pass");

на общем сервере веб-хостинга, и я получил ошибку:

System.Security.Cryptography.CryptographicException: An internal error occurred.

трассировка стека заканчивается на

System.Security.Cryptography.CryptographicException.
    ThrowCryptogaphicException(Int32 hr) +33
System.Security.Cryptography.X509Certificates.X509Utils.
    _LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, 
        Boolean persistKeySet, SafeCertContextHandle& pCertCtx) +0
System.Security.Cryptography.X509Certificates.X509Certificate.
    LoadCertificateFromFile(String fileName, Object password, 
        X509KeyStorageFlags keyStorageFlags) +237
System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(
    String fileName, String password) +131

На моей машине dev загружается нормально. Причина, по которой я загружаю * .pfx, а не файл * .cer, потому что мне нужен доступ к закрытому ключу (файл cer загружается нормально). Я сделал pfx на моем dev mochine вот так:

makecert -r -n "CN=myhost.com, E=admin@myhost.com" -sky exchange -b 01/01/2009
    -pe -sv myhost.pvk myhost.cer
<b>pvk2pfx</b> -pvk myhost.pvk -spc myhost.cer -pfx myhost.pfx -po pass</code>

Я использую makecert версии v5.131.3790.0

casperOne
источник
Возможно, эта статья может помочь: codeproject.com/KB/WCF/wcfcertificates.aspx
Эммануэль
Я получал сообщение об ошибке the system cannot find the file specified. Ответ @Randy Levy сработал для меня!
Джесс

Ответы:

145

Используйте хранилище локального компьютера для закрытого ключа:

X509Certificate2 cert = new X509Certificate2("myhost.pfx", "pass",
    X509KeyStorageFlags.MachineKeySet);

MachineKeySetописывается как «личные ключи хранятся в хранилище локального компьютера, а не в хранилище текущего пользователя». По умолчанию без флагов помещается в пользовательское хранилище.

Даже если вы читаете сертификат с диска и сохраняете его в объекте, закрытые ключи по-прежнему хранятся в базе данных ключей Microsoft Cryptographic API Cryptographic Service Provider. На хост-сервере процесс ASP.NET не имеет разрешения на доступ к хранилищу пользователей.

Другой подход (согласно некоторым комментариям ниже) - изменить конфигурацию IIS или удостоверение пула приложений, которые действительно работают. Однако это предполагает, что есть доступ к этим элементам конфигурации, что может быть не так (например, в среде общего хостинга).

Рэнди поддерживает Монику
источник
3
да, это помогает, спасибо. не могли бы вы объяснить почему? в документации нет ничего полезного.
2
Ты спас мне день. Как ни странно, на моей машине он работал до обновления решения до .NET 4.0
Марк Климент,
1
Действительно, все, что нужно было сделать, это установить параметр X509KeyStorageFlags.MachineKeySet. Очень грустно, что выброшенное исключение просто сообщает «Произошла внутренняя ошибка». Не очень полезно.
Nicholi
2
Вы также можете добавить дополнительные привилегии к закрытому ключу учетной записи, назначенной пулу приложений. Или измените идентификатор пула приложений на «Локальная служба».
guzart
1
И для более быстрой проверки исправления / обходного пути: stackoverflow.com/questions/9951729/…
Сиприан Тейосану 02 окт.13,
13

Я попробовал изменить его на MachineKeySet, предложенный Рэнди, но затем получил сообщение об ошибке:

"ключ недействителен для использования в указанном состоянии"

Итак, после небольшого поиска в Google я нашел сообщение, в котором предлагалось изменить его на:

var certificate = new X509Certificate2(certKeyFilePath, passCode, 
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet |       
X509KeyStorageFlags.PersistKeySet );

и это решило мои проблемы.

Я еще не пробовал изменить настройку пула приложений в конфигурации IIS. Для этого перейдите в расширенные настройки для пула приложений вашего сайта и установите для параметра «загрузить профиль пользователя» значение true. Если для этого параметра установлено значение false, очевидно, что ключевые контейнеры недоступны.

Майк Блэк
источник
Я получал вышеупомянутую ошибку, и ваше решение помогло ее решить. благодарю вас.
dotcoder
Я не люблю комментарии, которые не помогают (например, этот), но позвольте мне сказать вам, что вы спасаете мне день. Благодаря!
rasputino