Исключение Конструктора X509Certificate


//cert is an EF Entity and 
//    cert.CertificatePKCS12 is a byte[] with the certificate.

var certificate = new X509Certificate(cert.CertificatePKCS12, "SomePassword");

при загрузке сертификата из нашей базы данных, на нашем промежуточном сервере (Windows 2008 R2 / IIS7. 5) мы получаем это исключение:

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

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
   at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)

Примечание: эта проблема не происходит локально (Windows 7/Casini).

любое понимание будет высоко оценен.

7 63

7 ответов:

оказывается, в конфигурации пула приложений IIS (пулы приложений > Дополнительные параметры) есть параметр для загрузки профиля пользователя для пользователя удостоверения пула приложений. Если установлено значение false, контейнеры ключей недоступны.

Так что просто установите Как True

App Pool-> Advanced Settings Screen

скорее всего, когда вы работаете с Visual Studio / Cassini, он обращается к вашему пользователей хранилище сертификатов, даже если вы загружаете его из байтов. Не могли бы вы попробовать это и посмотреть, если это решает вашу проблему:

var certificate = new X509Certificate(
    cert.CertificatePKCS12, "SomePassword", X509KeyStorageFlags.MachineKeySet);

это вызовет IIS (который работает как ASP.NET пользователь, который, вероятно, не имеет доступа к пользовательскому хранилищу), чтобы использовать машинное хранилище.

на этой странице объясняет конструктор более подробно, и этот страница объясняются X509KeyStorageFlags перечисление.

Edit: На основе вторая ссылка С cyphr, похоже, что это может быть хорошей идеей (если предыдущее решение не работает), чтобы объединить некоторые из FlagsAttribute перечисление значений так:

var certificate = new X509Certificate(
    cert.CertificatePKCS12, "SomePassword",
    X509KeyStorageFlags.MachineKeySet
    | X509KeyStorageFlags.PersistKeySet
    | X509KeyStorageFlags.Exportable);

кроме того, если у вас есть доступ, вы можете попробовать изменить настройки пула приложений для использования LocalService (а затем перезапустить AppPool). Это может поднять ваш разрешения на соответствующий уровень, если это проблема.

наконец, вы можете использовать File.WriteAllBytes написать CertificatePKCS12 содержимое в pfx-файл и посмотреть, если вы можете вручную импортировать его с помощью консоли сертификата под MMC (вы можете удалить после успешного импорта; это просто для тестирования). Это может быть, что ваши данные получают munged, или пароль неверен.

используйте этот код:

certificate = new X509Certificate2(System.IO.File.ReadAllBytes(p12File)
                                   , p12FilePassword
                                   , X509KeyStorageFlags.MachineKeySet |
                                     X509KeyStorageFlags.PersistKeySet | 
                                     X509KeyStorageFlags.Exportable);

У меня были проблемы на Windows 2012 Server R2, где мое приложение не может загрузить сертификаты для PFX на диске. Все будет работать нормально, запустив мое приложение в качестве администратора, и исключение сказало, что доступ запрещен, поэтому это должна быть проблема с разрешениями. Я попробовал некоторые из вышеперечисленных советов, но у меня все еще была проблема. Я обнаружил, что указание следующих флагов в качестве третьего параметра конструктора cert сделало трюк для меня:

 X509KeyStorageFlags.UserKeySet | 
 X509KeyStorageFlags.PersistKeySet | 
 X509KeyStorageFlags.Exportable

чтобы действительно решить вашу проблему, а не просто догадаться, что это может быть, нужно уметь воспроизвести вашу проблему.. Если вы не можете предоставить тестовый файл PFX, который имеет ту же проблему, вы должны изучить проблему самостоятельно. Первый важный вопрос: Является ли происхождение исключения "внутренней ошибкой" в части закрытого ключа PKCS12 или в открытой части самого сертификата?

поэтому я бы рекомендовал вам попробовать повторить то же самое поэкспериментируйте с тем же сертификатом, экспортированным без закрытого ключа (как .CER file):

var certificate = new X509Certificate(cert.CertificateCER);

или

var certificate = new X509Certificate.CreateFromCertFile("My.cer");

это может помочь проверить, является ли происхождение вашей проблемы является закрытый ключ или некоторые свойства сертификата.

если у вас возникнут проблемы с файлом CER, вы можете безопасно разместить ссылку на файл, потому что у него есть только общедоступная информация. В качестве альтернативы вы можете, по крайней мере выполнить

CertUtil.exe -dump -v "My.cer"

или

CertUtil.exe -dump -v -privatekey -p SomePassword "My.pfx"

(вы можете использовать некоторые другие варианты тоже) и пост некоторые части вывода (например свойства закрытого ключа без самого PRIVATEKEYBLOB).

альтернативой изменению профиля пользователя Load является использование пулом приложений Сетевая Служба личность.

см. также что именно происходит, когда я устанавливаю LoadUserProfile пула IIS?

вам нужно импортировать a .сертификат cer для вашего локального хранилища ключей компьютера. Нет необходимости импортировать .P12 cert-вместо этого используйте второй сертификат, выданный вашей учетной записи Apple. Я думаю, что это должна быть действительная пара сертификатов (один в файловой системе, второй в хранилище ключей). Вы должны будете установить все 3 флага в dll, конечно.