CryptographicException "Keyset не существует", но только через WCF

У меня есть код, который вызывает вызов сторонней веб-службы, которая защищена с помощью сертификации X.509.

Если я вызываю код напрямую (используя unit test), он работает без проблем.

При развертывании этот код будет вызываться через службу WCF. Я добавил второй unit test, который вызывает службу WCF, однако это не удается с сообщением CryptographicException, message "Keyset does not exist", когда я вызываю метод в сторонней веб-службе.

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

Может ли кто-нибудь пролить дополнительный свет на эту проблему?

Ответ 1

Вероятно, это проблема с разрешениями в сертификате.

При запуске unit test вы будете запускать те, которые находятся в вашем пользовательском контексте, которые (в зависимости от того, в каком хранилище находится клиентский сертификат) будут иметь доступ к этому закрытому ключу сертификата.

Однако, если ваша служба WCF размещена в IIS или в качестве службы Windows, скорее всего, она будет запущена под учетной записью службы (Network Service, Local Service или другая ограниченная учетная запись).

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

Ответ 2

Это, скорее всего, потому, что пользователь IIS не имеет доступа к закрытому ключу для вашего сертификата. Вы можете установить это, выполнив следующие шаги...

  • Пуск → Выполнить → MMC
  • Файл → Добавить/удалить Snapin
  • Добавить привязку сертификатов
  • Выберите "Учетная запись компьютера", затем нажмите "Далее"
  • Выберите локальный компьютер (по умолчанию), затем нажмите "Готово"
  • На левой панели от корня консоли перейдите к  Сертификаты (локальный компьютер) → Персональные → Сертификаты
  • Ваш сертификат, скорее всего, будет здесь.
  • Щелкните правой кнопкой мыши на своем сертификате → Все задачи → Управление приватными ключами
  • Задайте здесь настройки своего личного ключа.

Ответ 3

У меня был такой же вопрос прошлой ночью. Разрешения на закрытый ключ были установлены правильно, все было, по-видимому, прекрасно, за исключением того, что Keyset не существует ошибки. В итоге оказалось, что сертификат сначала был импортирован в текущее хранилище пользователей, а затем перемещен в локальное хранилище. Однако - это не переместило закрытый ключ, который все еще находился в

C:\Documents and settngs\Administrator...

вместо

C:\Documents and settngs\All users...

Уверенные права на ключ были установлены правильно, ASPNET не смог получить к нему доступ. Когда мы повторно импортируем сертификат, чтобы закрытый ключ был помещен во ветку "Все пользователи", проблема исчезла.

Ответ 4

Чтобы разрешить "Keyset не существует" при просмотре в IIS: Это может быть личное разрешение

Чтобы просмотреть и предоставить разрешение:

  • Run > ММС > да
  • щелкните по файлу
  • Нажмите "Добавить/удалить оснастку"...
  • Дважды щелкните по сертификату
  • Учетная запись компьютера
  • Далее
  • Готово
  • Ok
  • Нажмите "Сертификаты" (локальный компьютер)
  • Нажмите "Личное"
  • Нажмите "Сертификаты"

Чтобы предоставить разрешение:

  • Щелкните правой кнопкой мыши имя сертификата
  • Все задачи > Управление приватными ключами...
  • Добавить и предоставить привилегию (добавив IIS_IUSRS и предоставив ему привилегию для меня)

Ответ 5

Имела ту же проблему при попытке запустить приложение WCF из Visual Studio. Решил его, запустив Visual Studio в качестве администратора.

Ответ 6

Я столкнулся с этой проблемой, мои сертификаты, где есть закрытый ключ, но я получал эту ошибку ("Ключ не существует" )

Причина: Ваш веб-сайт работает под учетной записью "Сетевые службы" или имеет меньше привилегий.

Решение: измените идентификатор пула приложений на "Локальная система", reset IIS и снова проверьте. Если он начинает работать, это проблема с полномочиями/меньшей привилегией, вы можете выдавать себя за другое использование и других учетных записей.

Ответ 7

В целом разочарование, у меня была такая же проблема, и я попробовал большую часть из вышеперечисленных. У экспортированного сертификата правильно были разрешения на чтение файла в C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, однако, как оказалось, у него не было разрешения на эту папку. Добавлено его, и он работал

Ответ 8

У меня точно такая же проблема. Я использовал команду

findprivatekey root localmachine -n "CN="CertName" 

результат показывает, что закрытый ключ находится в папке c:\ProgramData вместо C:\Documents and settngs\All users..

Когда я удаляю ключ из папки c:\ProgramData, снова запустить команду findPrivatekey не удастся. то есть. он не находит ключ.

Но если я ищу тот же ключ, который был возвращен предыдущей командой, я все равно могу найти ключ в

C:\Documents and settngs\All users..

Поэтому, насколько я понимаю, IIS или размещенный WCF не находят закрытый ключ из C:\Documents and settngs\All users..

Ответ 9

Я получал ошибку: CryptographicException "Keyset не существует" при запуске приложения MVC.

Решением было: предоставить доступ к персональным сертификатам учетной записи, в которой работает пул приложений. В моем случае я должен был добавить IIS_IUSRS и выбрать правильное местоположение, разрешив эту проблему.

RC on the Certificate - > All tasks -> Manage Private Keys -> Add->  
For the From this location : Click on Locations and make sure to select the Server name. 
In the Enter the object names to select : IIS_IUSRS and click ok. 

Ответ 10

Я обнаружил недостающую информацию, которая помогла мне получить мою службу WCF с защитой уровня сообщений, когда "Ключ не существует", на котором я продолжал работать, несмотря на предоставление разрешений всем ключам, сгенерированным на примерах в Интернете.

Наконец, я импортировал закрытый ключ в хранилище доверенных лиц на локальном компьютере, а затем предоставил личный ключ правильные разрешения.

Это заполнило пробелы для меня и, наконец, позволило мне реализовать службу WCF с безопасностью уровня сообщений. Я создаю WCF, который должен соответствовать требованиям HIPPA.

Ответ 11

Ответ от Стива Шелдона устранил проблему для меня, однако, поскольку я использую разрешения на сертификаты для сценариев без графического интерфейса, мне нужно было решение с возможностью создания сценариев. Я изо всех сил пытался найти, где хранится мой закрытый ключ. Закрытого ключа не было в -C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, в конце концов я обнаружил, что на самом деле он был в C:\ProgramData\Microsoft\Crypto\Keys. Ниже я опишу, как я это узнал:

Я попытался FindPrivateKey, но он не смог найти закрытый ключ, и с помощью powershell $cert.privatekey.cspkeycontainerinfo.uniquekeycontainername был нулевым/пустым.

К счастью, certutil -store my перечислил сертификат и дал мне подробную информацию, необходимую для написания сценария решения.

================ Certificate 1 ================ Serial Number: 162f1b54fe78c7c8fa9df09 Issuer: CN=*.internal.xxxxxxx.net NotBefore: 23/08/2019 14:04 NotAfter: 23/02/2020 14:24 Subject: CN=*.xxxxxxxnet Signature matches Public Key Root Certificate: Subject matches Issuer Cert Hash(sha1): xxxxa5f0e9f0ac8b7dd634xx Key Container = {407EC7EF-8701-42BF-993F-CDEF8328DD} Unique container name: 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a ##* ^-- filename for private key*## Provider = Microsoft Software Key Storage Provider Private key is NOT plain text exportable Encryption test passed CertUtil: -store command completed successfully.

Затем я отсканировал папку c\ProgramData\Microsoft\Crypto\ и нашел файл 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a в C:\ProgramData\Microsoft\Crypto\Keys.

Предоставление моей учетной записи службы доступа к этому файлу устранило проблемы для меня

Ответ 12

Если вы используете ApplicationPoolIdentity для пула приложений, у вас может возникнуть проблема с указанием разрешения для этого "виртуального" пользователя в редакторе реестра (в системе нет такого пользователя).

Итак, используйте subinacl - средство командной строки, которое позволяет установить ACL реестра реестра или что-то вроде этого.

Ответ 13

Я просто хотел добавить ответ проверки здравомыслия. Я получал такую ​​же ошибку даже после установки сертификатов в нужные магазины на моих машинах и имеющих все права на безопасность для клиента. Оказывается, я перепутал свой клиентский сертификат и мой сертификат сервиса. Если вы попробовали все вышеперечисленное, я бы дважды проверить, что у вас есть эти два прямых. Как только я это сделал, мое приложение успешно вызвало веб-службу. Опять же, просто проверка правильности.

Ответ 14

Получил эту ошибку при использовании Fedora OpenAM на IIS7

Изменение учетной записи пользователя для веб-сайта по умолчанию разрешило проблему. В идеале вы хотели бы, чтобы это была учетная запись службы. Возможно, даже учетная запись IUSR. Предложите методы поиска для упрощения IIS, чтобы полностью уничтожить его.

Ответ 15

Я столкнулся с этим в своем проекте сервисной фабрики после того, как истек срок действия сертификата, который использовался для аутентификации в нашем хранилище ключей, и изменился, что изменило отпечаток. Я получил эту ошибку, потому что я пропустил обновление отпечатка в файле applicationManifest.xml в этом блоке, который точно выполняет то, что предлагали другие ответы - для предоставления NETWORK SERVICE (как все мои exe файлы, стандартные конфигурации для кластера Azure Service Fabric) для получить доступ к магазину LOCALMACHINE\MY cert.

Обратите внимание на значение атрибута "X509FindValue".

<!-- this block added to allow low priv processes (such as service fabric processes) that run as NETWORK SERVICE to read certificates from the store -->
  <Principals>
    <Users>
      <User Name="NetworkService" AccountType="NetworkService" />
    </Users>
  </Principals>
  <Policies>
    <SecurityAccessPolicies>
      <SecurityAccessPolicy ResourceRef="AzureKeyvaultClientCertificate" PrincipalRef="NetworkService" GrantRights="Full" ResourceType="Certificate" />
    </SecurityAccessPolicies>
  </Policies>
  <Certificates>
    <SecretsCertificate X509FindValue="[[THIS KEY ALSO NEEDS TO BE UPDATED]]" Name="AzureKeyvaultClientCertificate" />
  </Certificates>
  <!-- end block -->

Ответ 16

Я просто переустановил свой сертификат на локальной машине, а затем он работает нормально

Ответ 17

Это единственное решение, сработавшее для меня.

    // creates the CspParameters object and sets the key container name used to store the RSA key pair
    CspParameters cp = new CspParameters();
    cp.KeyContainerName = "MyKeyContainerName"; //Eg: Friendly name

    // instantiates the rsa instance accessing the key container MyKeyContainerName
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
    // add the below line to delete the key entry in MyKeyContainerName
    // rsa.PersistKeyInCsp = false;

    //writes out the current key pair used in the rsa instance
    Console.WriteLine("Key is : \n" + rsa.ToXmlString(true));

Ссылка 1

Ссылка 2