Как можно построить 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();
Ответы
Ответ 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]()