2009-02-17 7 views
9

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

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

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

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

[UPDATE: Подробнее]
Эта ошибка появляется в журнале событий 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 

Любые идеи?

ответ

8

Я только что нашел решение этой одной себя:

X509KeyStorageFlags flags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet; 

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

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

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

+0

Почему пользовательский контекст ASP.Net, который вы запускаете, не имеет доступа к своему собственному магазину? (Это решило мою проблему - это был классический «Но это работает на моей машине-разработчике! Просто любопытно рассуждать»). – DFTR

2

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

+0

Я думаю, что вы на правильном пути, но, похоже, он не пытается получить доступ к файловой системе. Учетная запись, которой удалось получить доступ к Microsoft \ Crypto \ RSA в личном профиле пользователя (не AllUsers). То, что не удается, даже не пытается получить доступ к файловой системе, согласно procmon. – jlew

+0

Это разрешение изменилось для меня на Win2k8. Сохранял мне кучу времени отладки. Благодаря! – CodingWithSpike

 Смежные вопросы

  • Нет связанных вопросов^_^