Почему X509Certificate2 иногда не удается создать из большого двоичного объекта? - PullRequest
10 голосов
/ 17 февраля 2009

У меня есть веб-служба ASP.NET, которая получает байтовый массив, представляющий содержимое файла .pfx, содержащего сертификат X.509. Код на стороне сервера использует конструктор System.Security.Cryptography.X509Certificate2 для загрузки сертификата из байтов:

X509Certificate2 native_cert = new X509Certificate2(
                pkcs12_buf /*byte array*/,
                password,
                X509KeyStorageFlags.PersistKeySet |
                X509KeyStorageFlags.Exportable
            );

В зависимости от того, от кого запущен мой сервисный процесс, этот вызов либо завершится успешно, либо завершится с ошибкой «внутренняя ошибка». Последний вызов в стеке исключений - X509Utils._LoadCertFromBlob, который является неуправляемым кодом в mscore.dll.

Этот код успешно выполняется при запуске из консольного приложения при интерактивном входе в систему с использованием учетных данных учетной записи службы. Сбой при запуске под w3wp.exe в пуле приложений, который использует учетные данные учетной записи службы. Изменение удостоверения пула приложений на администратора устраняет проблему, поэтому это должно быть проблемой с привилегиями, но я понятия не имею, какие привилегии могут быть необходимы для этого. Код не касается ни файловой системы, ни хранилищ сертификатов Windows.

[ОБНОВЛЕНИЕ: Больше информации]
Эта ошибка появляется в журнале событий Windows:

*Cryptographic Parameters:*   
**Provider Name:**  Microsoft Software Key Storage Provider  
**Algorithm Name:** Not Available.  
**Key Name:**   {E182E13B-166D-472A-A24A-CBEF0808E9ED}  
    **Key Type:**   User key.

*Cryptographic Operation:*  
**Operation:**  Open Key.  
    **Return Code:**    0x2  

Есть идеи?

Ответы [ 2 ]

9 голосов
/ 27 февраля 2009

Я сам нашел решение этой проблемы:

X509KeyStorageFlags flags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet;

X509Certificate2 cert = new X509Certificate2(pkcs12_buf, password, flags);

Хитрость здесь в том, чтобы использовать локальное хранилище ключей MachineKeySet вместо хранилища ключей профиля пользователя, которое используется по умолчанию, если вы не указали альтернативное местоположение. Поскольку удостоверение процесса ASP.NET не загружает хранилище профилей пользователей, вы не можете получить доступ к хранилищу при программном импорте сертификата, но вы можете получить доступ к хранилищу компьютеров.

Я думаю, что PersistKeySet просто хранит закрытый ключ, но я не уверен, что именно он делает - это требуется, если вам по какой-то причине требуется доступ к закрытому ключу.

2 голосов
/ 17 февраля 2009

Попробуйте предоставить разрешения учетной записи ASP.NET для следующей папки: C:\Documents And Settings\All Users\Microsoft\Crypto\RSA\MachineKeys\ (может варьироваться в зависимости от вашей среды)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...