Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline eight  
#1 Оставлено : 15 июня 2015 г. 20:35:45(UTC)
eight

Статус: Новичок

Группы: Участники
Зарегистрирован: 20.01.2015(UTC)
Сообщений: 6
Российская Федерация
Откуда: moscow

Здравствуйте! В нашем проекте активно используется КриптоПро. Есть небольшой сервер который реализует подписывание данных.
Сертификат из хранилища получается при помощи CertFindCertificateInStore, поиск осуществляется по Subject'у с указанием флага CERT_FIND_SUBJECT_STR.
Проблема в том, что находятся сертификаты с английскими символами в Subject, сертификаты с русскими символами в Subject'e не возможно найти.
Как это сделать не понятно, ваш форум читали. Всё это происходит под линуксом. Сервер получает строку UTF-8.

// Это кусок кода функции, которая использовалась для получения сертификата с английским subject'ом.
////////////////////////////////////////////////////////
bool getCertificateContext(const HCERTSTORE hCertStore,
const std::string &keyName,
PCCERT_CONTEXT &pCertContext) {

pCertContext = CertFindCertificateInStore(
hCertStore, // Дескриптор хранилища, в котором будет осуществлен поиск.
TYPE_DER, // Тип зашифрования. В этом поиске не используется.
0, // dwFindFlags. Специальный критерий поиска.
CERT_FIND_SUBJECT_STR, // Тип поиска. Задает вид поиска, который будет
keyName.c_str(), // pvFindPara. Выдает определенное значение поиска
0); // pCertContext равен NULL для первого вызова

/////////////////////////////////////////////////////////////////

//
// Это второй метод, который был написан для получения сертификата с кириллическими символами в subject'e.
// Сервер получает UTF-8 строку, преобразовывает её в UTF-32 и создает std::wstring.
// В UTF-32 переводим потому что sizeof(wchar_t) = 4 байта.
//
bool getCertificateContext0(const HCERTSTORE hCertStore,
const std::wstring &keyName,
PCCERT_CONTEXT &pCertContext) {

pCertContext = CertFindCertificateInStore(
hCertStore, // Дескриптор хранилища, в котором будет осуществлен поиск.
TYPE_DER, // Тип зашифрования. В этом поиске не используется.
0, // dwFindFlags. Специальный критерий поиска.
CERT_FIND_SUBJECT_STR_W, // Тип поиска. Задает вид поиска, который будет
keyName.c_str(), // pvFindPara. Выдает определенное значение поиска
0); // pCertContext равен NULL для первого вызова

Можно ли вообще находить сертификат в хранилище по кириллическому subject'у ? Если да, то как это сделать?
Offline cross  
#2 Оставлено : 16 июня 2015 г. 10:14:18(UTC)
Анатолий Беляев

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 24.11.2009(UTC)
Сообщений: 965
Откуда: Crypto-Pro

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 174 раз в 152 постах
Используйте MultiByteToWideChar(CP_UTF8....) для перекодировки
Техническую поддержку оказываем тут.
Наша база знаний.
Наша страничка в Instagram.
Offline eight  
#3 Оставлено : 16 июня 2015 г. 13:24:28(UTC)
eight

Статус: Новичок

Группы: Участники
Зарегистрирован: 20.01.2015(UTC)
Сообщений: 6
Российская Федерация
Откуда: moscow

Автор: cross Перейти к цитате
Используйте MultiByteToWideChar(CP_UTF8....) для перекодировки


Это WinApi. В теме указал Linux, в тексте так же упомянул этот момент.
Для конвертации используется iconv.

Код:
std::wstring getFromUtf8(const char* p, std::size_t length)
{
	std::wstring strConverted;
	wchar_t buffer[1024];
	memset(buffer, 0, sizeof(buffer));
	wchar_t inBuf[1024];
	memset(inBuf, 0, sizeof(inBuf));
	memcpy(inBuf, p, length);

	wchar_t* ptrInBuf = (wchar_t*)inBuf;
	std::size_t insize = length;
	wchar_t* pbuf = buffer;
	std::size_t outsize = sizeof(buffer);

	iconv_t hIcon = iconv_open("UTF-32", "UTF-8");
	std::size_t converted = iconv(hIcon, (char **)&ptrInBuf, (std::size_t*)&insize, (char**)&pbuf, (std::size_t*)&outsize);
	int conv_error = errno;
	iconv_close(hIcon);

	if(converted != -1){
		strConverted = std::wstring(buffer);
	}
	return strConverted;
}

Offline cross  
#4 Оставлено : 16 июня 2015 г. 15:40:25(UTC)
Анатолий Беляев

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 24.11.2009(UTC)
Сообщений: 965
Откуда: Crypto-Pro

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 174 раз в 152 постах
CertFindCertificateInStore тоже WinAPI ))

cross@cross7:/dailybuilds/CSPbuild$ nm /opt/cprocsp/lib/amd64/librdrsup.so | grep Mult
0000000000021588 T MultiByteToWideChar
000000000002197d T WideCharToMultiByte
Техническую поддержку оказываем тут.
Наша база знаний.
Наша страничка в Instagram.
Offline eight  
#5 Оставлено : 17 июня 2015 г. 21:27:47(UTC)
eight

Статус: Новичок

Группы: Участники
Зарегистрирован: 20.01.2015(UTC)
Сообщений: 6
Российская Федерация
Откуда: moscow

Автор: cross Перейти к цитате
CertFindCertificateInStore тоже WinAPI ))

cross@cross7:/dailybuilds/CSPbuild$ nm /opt/cprocsp/lib/amd64/librdrsup.so | grep Mult
0000000000021588 T MultiByteToWideChar
000000000002197d T WideCharToMultiByte


Спасибо за рекомендацию. Использовали.
Ситуация не изменилась. Схема у нас та же - получаем base64 строку, распаковываем, получаем utf-8 строку с кириллическими символами.

Функция перекодировки:

Код:
namespace converter
{
	std::string ws_s(const std::wstring& s, UINT cp)
	{
		int slength = (int)s.length() + 1;
		int len = WideCharToMultiByte(cp, 0, s.c_str(), slength, 0, 0, 0, 0);
		std::string r(len, '\0');
		WideCharToMultiByte(cp, 0, s.c_str(), slength, &r[0], len, 0, 0);
		return r;
	}

	std::wstring s_ws(const std::string& s, UINT cp)
	{
		int slength = (int)s.length() + 1;
		int len = MultiByteToWideChar(cp, 0, s.c_str(), slength, 0, 0);
		std::wstring r(len, L'\0');
		MultiByteToWideChar(cp, 0, s.c_str(), slength, &r[0], len);
		return r;
	}
}

std::wstring getFromUtf8(const char* p, std::size_t length)
{
	return converter::s_ws(p, CP_UTF8);
}


Так поиск сертификата осуществляется.

Код:
bool getCertificateContext0(const HCERTSTORE hCertStore,
                           const std::wstring &keyName,
                           PCCERT_CONTEXT &pCertContext) {
    bool result = false;

    pCertContext = CertFindCertificateInStore( 
        hCertStore,            // Дескриптор хранилища, в котором будет осуществлен поиск. 
        TYPE_DER,              // Тип зашифрования. В этом поиске не используется. 
        0,                     // dwFindFlags. Специальный критерий поиска. 
        CERT_FIND_SUBJECT_STR_W, // Тип поиска. Задает вид поиска, который будет
        keyName.c_str(),       // pvFindPara. Выдает определенное значение поиска
        0);         // pCertContext равен NULL для первого вызова  

    if (!pCertContext) {
    	printlog(CMS_SERV_LOG, "getCertificateContext0 certificate wasn't found.");
    } else {
        result = true;
        printlog(CMS_SERV_LOG, "getCertificateContext0 certificate found.");
    }
    return result; 
}


Ничего по-прежнему не находится.
Возможно ли найти сертификат по subject'у с кириллическими символами?


Offline eight  
#6 Оставлено : 22 июня 2015 г. 16:20:18(UTC)
eight

Статус: Новичок

Группы: Участники
Зарегистрирован: 20.01.2015(UTC)
Сообщений: 6
Российская Федерация
Откуда: moscow

Товарищи, ответ можно получить?
Нужен комментарий по нашему вопросу.
Offline cross  
#7 Оставлено : 22 июня 2015 г. 18:49:15(UTC)
Анатолий Беляев

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 24.11.2009(UTC)
Сообщений: 965
Откуда: Crypto-Pro

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 174 раз в 152 постах
Сделал небольшой пример. Сделал сертификат с СN="Фамилия Имя Отчество" и дальше вот такой код.

const char *lname = "Фамилия Имя Отчество";
wchar_t name[255];
memset(name, 0, sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, lname, 38, name, 255);
pCertContext = CertFindCertificateInStore(.....name)
if(pCertContext)....

файл в utf-8 кодировке.
Смотрю в дебагере
x/20x lname
0x4025f0: 0xb0d0a4d0 0xb8d0bcd0 0xb8d0bbd0 0xd0208fd1
0x402600: 0xd1bcd098 0x9ed0208f 0x87d182d1 0x81d1b5d0
0x402610: 0xb2d082d1 0x4500bed0
Что соответствует utf8 кодированной строке
Смотрим после конвертации на name
(gdb) x/20x name
0x7fffffffae30: 0x00000424 0x00000430 0x0000043c 0x00000438
0x7fffffffae40: 0x0000043b 0x00000438 0x0000044f 0x00000020
0x7fffffffae50: 0x00000418 0x0000043c 0x0000044f 0x00000020
0x7fffffffae60: 0x0000041e 0x00000442 0x00000447 0x00000435
0x7fffffffae70: 0x00000441 0x00000442 0x00000432 0x0000043e

что соответствует Unicode строке. После CertFindCertificateInStore
(gdb) p pCertContext->pCertInfo.SerialNumber.pbData
$43 = (BYTE *) 0x63f0a8 "`|"
(gdb) x/10x 0x63f0a8
0x63f0a8: 0x00007c60 0x266b0000 0x00003dfd

Совпадает с серийником который выводит certmgr
Serial : 0x3DFD266B000000007C60


Техническую поддержку оказываем тут.
Наша база знаний.
Наша страничка в Instagram.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (3)
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.