Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.06.2019(UTC) Сообщений: 30 Откуда: Самара Сказал(а) «Спасибо»: 4 раз
|
Параметры системы: Linux 3.10.0-957.12.2.el7.x86_64 CentOS Linux Release 7.6.1810 CryptoPro установлена со стандартной лецензией на 3 месяца. Отдельно не активировалась. Пишу код на .NET Core 2.1. Все вызовы делаю через P/Invoke. На Windows вызовы работают. Проблема: Вызываю в Linux из библиотеки "libcapi20" функцию CryptAcquireContext, с аналогичными параметрами как и в windows. var provider = IntPtr.Zero; var name = "TEST"; var PROV_GOST_2012_256 = 80U; var CRYPT_NEWKEYSET = 8U; var CP_GR3410_2012_PROV_A "Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider"; var szOID_CP_GOST_R3410_12_256 = "1.2.643.7.1.1.1.1"; var result = CryptAcquireContext(provider, name, null, PROV_GOST_2012_256, CRYPT_NEWKEYSET); Пробовал менять точку входа на CryptAcquireContextA и CryptAcquireContextW (из документации CAPLite) но это не работает. Меняется после вызова только код ошибки. Код ошибки меняттся либо на 0 либо на -1; Результат всегда false. Менял флаги на 0, пробовал заналивать имя, но ничего не работает. (Я в одном примере работы с CryptAcquireContext(для создания нового контейнера) прочитал что второй параметр при первых вызовах присваивается null.) Пробовал подставлять вместо null CP_GR3410_2012_PROV_A а также szOID_CP_GOST_R3410_12_256. Прошу подсказать что я делаю не так? Отредактировано пользователем 28 июня 2019 г. 8:50:56(UTC)
| Причина: Не указана
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.09.2016(UTC) Сообщений: 126
Сказал(а) «Спасибо»: 8 раз Поблагодарили: 35 раз в 28 постах
|
Можно попробовать имя передать в формате: "\\.\HDIMAGE\TEST"
|
1 пользователь поблагодарил Aleksandr G* за этот пост.
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.01.2019(UTC) Сообщений: 43 Откуда: Москва Сказал(а) «Спасибо»: 3 раз Поблагодарили: 5 раз в 5 постах
|
Автор: EgorOkhotin Параметры системы: .... Прошу подсказать что я делаю не так? Насколько я помню, в линуксе лучше использовать *W функции при условии что нужно передавать UTF32 строки (в винде UTF16) стандартный маршаллер не в курсе и пытается строки передавать как в винде Поэтому используем самописный маршалинг строк Код:
public static class EncodingUtils
{
internal static IntPtr StringToPtrUni(string value)
{
if (value == null)
{
return IntPtr.Zero;
}
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
return StringToPtrUTF32(value);
}
return Marshal.StringToHGlobalUni(value);
}
private static IntPtr StringToPtrUTF32(string value)
{
var enc = Encoding.UTF32;
var utf32Bytes = new byte[enc.GetByteCount(value) + 4];
enc.GetBytes(value, 0, value.Length, utf32Bytes, 0);
var ptr = Marshal.AllocHGlobal(utf32Bytes.Length);
Marshal.Copy(utf32Bytes, 0, ptr, utf32Bytes.Length);
return ptr;
}
}
internal class UnmanageMemoryHolder : IDisposable
{
private List<IntPtr> _globalAllocations = new List<IntPtr>();
public void Dispose()
{
foreach (var globalAllocation in _globalAllocations)
{
Marshal.FreeHGlobal(globalAllocation);
}
_globalAllocations.Clear();
}
public IntPtr GetUniStringPtr(string strValue)
{
IntPtr ptr = EncodingUtils.StringToPtrUni(strValue);
_globalAllocations.Add(ptr);
return ptr;
}
}
Используем как то так Код:
[DllImport(s_Advapi32Dll, BestFitMapping = false, CharSet = CharSet.Auto, SetLastError = true,
ThrowOnUnmappableChar = true, EntryPoint = "CryptAcquireContextW")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CryptAcquireContext([In] [Out] ref SafeCryptProvHandle hProv,
[In] IntPtr pszContainer,
[In] IntPtr pszProvider,
[In] int dwProvType,
[In] [MarshalAs(UnmanagedType.U4)] AcqureContextFlags dwFlags);
internal static bool AcquireContext([In] [Out] ref SafeCryptProvHandle hProv,
string pszContainer,
string pszProvider,
int dwProvType,
AcqureContextFlags dwFlags)
{
var containerPtr = IntPtr.Zero;
var provPtr = IntPtr.Zero;
using (var holder = new UnmanageMemoryHolder())
{
containerPtr = pszContainer == null
? IntPtr.Zero
: holder.GetUniStringPtr(pszContainer);
provPtr = pszProvider == null
? IntPtr.Zero
: holder.GetUniStringPtr(pszProvider);
bool ret = CryptAcquireContext(ref hProv, containerPtr, provPtr, dwProvType, dwFlags);
if (ret)
return ret;
int hr = Crypt32.GetLastError();
if (hr == CryptErrors.ERROR_NO_UNICODE_TRANSLATION)
{
containerPtr = pszContainer == null
? IntPtr.Zero
: holder.GetAnsiStringPtr(pszContainer);
provPtr = pszProvider == null
? IntPtr.Zero
: holder.GetAnsiStringPtr(pszProvider);
return CryptAcquireContext(ref hProv, containerPtr, provPtr, dwProvType, dwFlags);
}
}
return false;
}
}
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 05.03.2015(UTC) Сообщений: 1,602 Откуда: Иркутская область Сказал(а) «Спасибо»: 110 раз Поблагодарили: 394 раз в 366 постах
|
Я бы наверно для начала создал контекст с флагом CRYPT_VERIFYCONTEXT и перечислил какие провайдеры вообще видны и какие их правильные написания под конкретной ОС. Для линуха обычно в названии фигурирует КС1 или КС2 (чего нет для виндоуз). Перечислил какие контейнеры уже есть, может быть один раз контейнер уже создался и второй раз ошибка из-за совпадения имени с существующим контейнером. Насчет прописывания 80 лучше бы особо не увлекаться - так как это означает что программа не сможет работать там где криптопро нет, у других компаний другие типы для провайдеров гост-2012. Что качается A или W то это надо выбрать в зависимости от того какой у Вас проект. Если проект записывает строки в память как Unicode (то есть символ с кодом 0 после каждого латинского символа, двойной 0 для конца строки), то W иначе (0 только в конце строки, не встречается в середине строки) A. Если выбрать неправильно, то или считается только первый символ каждой строки или выйдет неправдоподобный символ Юникода вместо двух символов. Вот уже сообщением выше и свой обработчик порекомендовали. Отредактировано пользователем 17 июня 2019 г. 11:57:04(UTC)
| Причина: Не указана
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.06.2019(UTC) Сообщений: 30 Откуда: Самара Сказал(а) «Спасибо»: 4 раз
|
Автор: migel Автор: EgorOkhotin Параметры системы: .... Прошу подсказать что я делаю не так? Насколько я помню, в линуксе лучше использовать *W функции при условии что нужно передавать UTF32 строки (в винде UTF16) стандартный маршаллер не в курсе и пытается строки передавать как в винде Поэтому используем самописный маршалинг строк Спасибо за ответ, но не работает.
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.06.2019(UTC) Сообщений: 30 Откуда: Самара Сказал(а) «Спасибо»: 4 раз
|
Автор: two_oceans Я бы наверно для начала создал контекст с флагом CRYPT_VERIFYCONTEXT и перечислил какие провайдеры вообще видны и какие их правильные написания под конкретной ОС. Для линуха обычно в названии фигурирует КС1 или КС2 (чего нет для виндоуз). Перечислил какие контейнеры уже есть, может быть один раз контейнер уже создался и второй раз ошибка из-за совпадения имени с существующим контейнером.
Насчет прописывания 80 лучше бы особо не увлекаться - так как это означает что программа не сможет работать там где криптопро нет, у других компаний другие типы для провайдеров гост-2012.
Что качается A или W то это надо выбрать в зависимости от того какой у Вас проект. Если проект записывает строки в память как Unicode (то есть символ с кодом 0 после каждого латинского символа, двойной 0 для конца строки), то W иначе (0 только в конце строки, не встречается в середине строки) A. Если выбрать неправильно, то или считается только первый символ каждой строки или выйдет неправдоподобный символ Юникода вместо двух символов. Вот уже сообщением выше и свой обработчик порекомендовали. С флагом CRYPT_VERIFYCONTEXT он возвращает true. Но перечисление выполнить не удалось, при попытке обратиться к CryptEnumProviders почему-то просто вылетает с кодо 0 немотря на точки остановки. Мне надо разобраться первоначально на линукс, а потом добавлю други возможности. А сейчас я мало представляю в чем дело. Я перечислял провайдеры с помощью утилиты cpcconfig и там 3 провайдера R 34-10. Коды 75, 80, 81
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.06.2019(UTC) Сообщений: 30 Откуда: Самара Сказал(а) «Спасибо»: 4 раз
|
Автор: Aleksandr G* Можно попробовать имя передать в формате: "\\.\HDIMAGE\TEST" Я не знаю что это за магия но сработало. Я просто не представляю обращение по такому пути в линукс, большое спасибо.
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.09.2016(UTC) Сообщений: 126
Сказал(а) «Спасибо»: 8 раз Поблагодарили: 35 раз в 28 постах
|
Автор: EgorOkhotin Я не знаю что это за магия но сработало. Я просто не представляю обращение по такому пути в линукс, большое спасибо.
Это имя контейнера с путем на жестком диске (хранилище КриптоПро). По идее если указывать короткое, то должно появляться окно с выбором (аналогичное windows, где реестр, диск, токен и т.д.), но не работает в 4 версии, в 5 можно и по короткому (могу ошибаться, лучше протестировать)
|
|
|
|
Статус: Сотрудник
Группы: Администраторы, Участники Зарегистрирован: 24.11.2009(UTC) Сообщений: 965 Откуда: Crypto-Pro
Сказал(а) «Спасибо»: 3 раз Поблагодарили: 174 раз в 152 постах
|
|
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close