Подтвердить что ты не робот

Как можно построить X509Certificate2 из массива байтов PKCS # 12 throw CryptographicException ( "Система не может найти указанный файл" )?

Я пытаюсь построить X509Certificate2 из блога PKCS # 12 в байтовом массиве и получить довольно загадочную ошибку. Этот код работает в настольном приложении с правами администратора в Windows XP.

Трассировка стека выглядит следующим образом, но я потерялся, пытаясь устранить неполадки, потому что _LoadCertFromBlob отмечен [MethodImpl(MethodImplOptions.InternalCall)].

System.Security.Cryptography.CryptographicException: The system cannot find the file specified.
  at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(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)
  at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)

РЕДАКТИРОВАТЬ: БЛОБ - это настоящий PKCS # 12, сгенерированный BouncyCastle для С#, содержащий закрытый ключ RSA и сертификат (самозаверяемый или недавно зарегистрированный в ЦС) - то, что я пытаюсь сделать, - это преобразовать закрытый ключ и сертификат из библиотеки BouncyCastle в библиотеку System.Security.Cryptography, экспортируя их из одного и импортируя в другой, Этот код работает на подавляющем большинстве систем, на которые он был опробован; Я никогда не видел, чтобы эта конкретная ошибка была выбрана из этого конструктора. Это может быть какая-то экологическая странность в этой коробке.

РЕДАКТИРОВАТЬ 2: Ошибка возникает в другой среде в другом городе, и я не могу воспроизвести ее локально, так что я могу закончить тем, установка.

Так как вы спрашивали, вот фрагмент, о котором идет речь. Код принимает закрытый ключ и сертификат в представлении BouncyCastle, удаляет все предыдущие сертификаты для одного и того же Distinguished Name из личного хранилища ключей и импортирует новый закрытый ключ и сертификат в хранилище личных ключей через промежуточное PKCS # 12 blob.

// open the personal keystore
var msMyStore = new X509Store(StoreName.My);
msMyStore.Open(OpenFlags.MaxAllowed);

// remove any certs previously issued for the same DN
var oldCerts =
    msMyStore.Certificates.Cast<X509Certificate2>()
        .Where(c => X509Name
                        .GetInstance(Asn1Object.FromByteArray(c.SubjectName.RawData))
                        .Equivalent(CurrentCertificate.SubjectDN))
        .ToArray();
if (oldCerts.Length > 0) msMyStore.RemoveRange(new X509Certificate2Collection(oldCerts));

// build a PKCS#12 blob from the private key and certificate
var pkcs12store = new Pkcs12StoreBuilder().Build();
pkcs12store.SetKeyEntry(_Pkcs12KeyName,
                        new AsymmetricKeyEntry(KeyPair.Private),
                        new[] {new X509CertificateEntry(CurrentCertificate)});
var pkcs12data = new MemoryStream();
pkcs12store.Save(pkcs12data, _Pkcs12Password.ToCharArray(), Random);

// and import it.  this constructor call blows up
_MyCertificate2 = new X509Certificate2(pkcs12data.ToArray(),
                                       _Pkcs12Password,
                                       X509KeyStorageFlags.Exportable);
msMyStore.Add(_MyCertificate2);
msMyStore.Close();
4b9b3361

Ответ 1

У вас есть PKCS # 12 или просто PFX файл? В мире Microsoft это одно и то же, но другие думают другое (см. http://www.drh-consultancy.demon.co.uk/pkcs12faq-old.html#PFX).

Вы можете попробовать просто следовать

X509Certificate2 cert = X509Certificate2(byte[] rawData, "password");
X509Certificate2 cert2 = X509Certificate2(byte[] rawData, "password",
              X509KeyStorageFlags.MachineKeySet |
              X509KeyStorageFlags.PersistKeySet |
              X509KeyStorageFlags.Exportable);

(см. http://msdn.microsoft.com/en-us/library/ms148418.aspx) или

X509Certificate2 cert = X509Certificate2("C:\Path\my.pfx", "password");

(см. http://msdn.microsoft.com/en-us/library/ms148420.aspx и http://msdn.microsoft.com/en-us/library/ms148442.aspx если вам нужно использовать некоторые флаги)

ОБНОВЛЕНО. Было бы полезно вставить фрагмент кода, а не только трассировку стека исключений.

Какой X509KeyStorageFlags вы используете? Вы можете использовать Process Monitor, чтобы узнать, какой файл не может найти конструктор X509Certificate2. Например, нет контейнера ключей по умолчанию для текущего пользователя в Windows XP, имеющего проблему. Вы можете создать его и повторить импорт.

Ответ 2

Я столкнулся с той же проблемой.

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

Из статьи:

Конструкторы класса X509Certificate2 пытаются импортировать сертификат в профиль пользователя учетной записи пользователя, в которой работает приложение. Много раз приложения ASP.NET и COM + олицетворяли клиентов. Когда они это делают, они не загружают пользовательские профили для олицетворенного пользователя по соображениям производительности. Таким образом, они не могут получить доступ к хранилищу сертификатов "Пользователь" для олицетворенного пользователя.

Загрузка профиля пользователя исправила ошибку.

Ответ 3

Запустив это в веб-приложении в Windows 2012, установите параметр пула приложений Load User Profile на true, чтобы он работал.

Для этого запустите inetmgr.exe, перейдите к Advanced Settings для правильного пула приложений, измените Load User Profile под Process Model на true.

Ответ 4

У меня была точно такая же проблема. Тот же код и данные/сертификаты отлично работали в Windows 2003 x86 при работе под определенным пользователем, но не выполнялись под другой учетной записью (которая также использовалась для запуска пулов приложений IIS).

По-видимому, некоторые другие ресурсы исчерпали ресурсы в Windows, так что неудачный пользователь не смог загрузить профиль пользователя (его рабочий стол был странным), хотя в Event Viewer не было связанных событий ,

Перезагрузка решила проблему временно. Хотя это не является постоянным решением проблемы, это показывает, что есть что-то еще (например, компоненты COM +, службы родного кода и т.д.), Потребляющие ресурсы, которые необходимо исследовать. Он также показывает нестабильность платформ Windows...

Ответ 5

У меня была такая же проблема.

  • Откройте IIS на сервере, на котором размещен сайт.
  • Найдите пул приложений для сайта.
  • Нажмите "Дополнительные настройки".
  • Измените "Загрузить профиль пользователя" на true. (может потребоваться перезагрузка или перезагрузка)

Это позволяет криптосистеме работать.

enter image description here