Статус: Участник
Группы: Участники
Зарегистрирован: 13.09.2022(UTC) Сообщений: 20 Откуда: Волгоград Сказал(а) «Спасибо»: 2 раз
|
Всем день добрый. Занимаюсь переносом некоторого кода с net core на net framework. Там использовал флаг CspNoPersistKeySet для загрузки сертификата вот так: Код:var cert = new X509Certificate2(certBytes, certPassword, X509KeyStorageFlags.CspNoPersistKeySet);
А как сделать чтобы тоже самое на Net Framework 4.8? Спасибо!
|
|
|
|
Статус: Сотрудник
Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC) Сообщений: 6,393 Откуда: КРИПТО-ПРО Сказал «Спасибо»: 37 раз Поблагодарили: 717 раз в 621 постах
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 13.09.2022(UTC) Сообщений: 20 Откуда: Волгоград Сказал(а) «Спасибо»: 2 раз
|
Автор: Максим Коллегин Спасибо за наводку, удалось набросать нечто похожее на работающий код: Код: public static X509Certificate2 FromFile(string filename, string password)
{
var handle = default(GCHandle);
var storePtr = IntPtr.Zero;
try
{ // Читаем файл сертификата
byte[] buffer = File.ReadAllBytes(filename);
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
CRYPT_DATA_BLOB cryptdata = new CRYPT_DATA_BLOB
{
cbData = buffer.Length,
pbData = handle.AddrOfPinnedObject()
};
// Открываем сертификат без хранения ключей.
if ((storePtr = PFXImportCertStore(ref cryptdata, password, PKCS12_NO_PERSIST_KEY | CRYPT_EXPORTABLE)) == IntPtr.Zero)
return null;
var certHandle = IntPtr.Zero;
while ((certHandle = CertEnumCertificatesInStore(storePtr, certHandle)) != IntPtr.Zero)
{
var size = 0;
// Получаем первый сертификат у которого есть приватный ключ (обычный или эфемерный).
if (CertGetCertificateContextProperty(certHandle, CERT_KEY_CONTEXT_PROP_ID, IntPtr.Zero, ref size)
|| CertGetCertificateContextProperty(certHandle, CERT_KEY_PROV_INFO_PROP_ID, IntPtr.Zero, ref size))
{
var dup = CertDuplicateCertificateContext(certHandle);
var crt = new X509Certificate2(dup);
return crt;
}
}
return null;
}
finally
{
if (storePtr != IntPtr.Zero)
CertCloseStore(storePtr, 0);
if (handle.IsAllocated)
handle.Free();
}
}
}
Но, тут странная вещь: если использовать этот код в net Core - то полученный сертификат полностью идентичен загруженному с CspNoPersistKeySet - отлично работает подписание. Но в net framework 4.8 НЕ работает, бросает исключение "Объект или свойство не найдено". Подпись получаю так: Код: private static string Sign(string str, X509Certificate2 cert)
{
try
{
// Тестируем подпись.
var file = string.IsNullOrEmpty(str)
? new byte[] { 1, 2, 3, 5, 5, 6 }
: Encoding.UTF8.GetBytes(str);
CmsSigner signer = new CmsSigner(cert);
ContentInfo contentInfo = new ContentInfo(file);
SignedCms signedCms = new SignedCms(contentInfo, detached: true);
signedCms.ComputeSignature(signer); // Вот на этой строчке происходит падение
return Convert.ToBase64String(signedCms.Encode());
}
catch (Exception exc)
{
return null;
}
}
Ну и в других операциях (например авторизации по сертификату) тоже сертификат не отрабатывает как надо. Что нужно улучшить здесь? Где может быть проблема?
|
|
|
|
Статус: Сотрудник
Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC) Сообщений: 6,393 Откуда: КРИПТО-ПРО Сказал «Спасибо»: 37 раз Поблагодарили: 717 раз в 621 постах
|
Проблема в ссылке на ключ скорее всего, попробуйте не закрывать хранилище. Вообще кэш в .NET устроен очень странно, постараюсь вспомнить точнее, если не разберётесь. Вспомнил, что лучше вообще не использовать SignedCms, он неверно работает со ссылками на криптопровайдер и при многопоточной работе гарантированы ошибки. Отредактировано пользователем 13 июля 2023 г. 14:44:26(UTC)
| Причина: Не указана |
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close