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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline yndtrud  
#1 Оставлено : 27 мая 2016 г. 9:40:15(UTC)
yndtrud

Статус: Участник

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

Сказал(а) «Спасибо»: 2 раз
Добрый день, знатоки. Прошу вас помочь, нубу )

Я новичок в CryptoAPI, хотел бы получить от вас умный совет.

Стоит задача: проверить подпись и найти сертификат (поверить, если он в exe или dll).
Модули подписаны сертификатом. Подпись легко проверил через WinTrast.

Нужно найти сертификат. Написал следующую функцию.
На входе имя файла, серийные номер сертификата, издатель
Насколько, я понимаю, сертификат встроен в модуль после выполнения (ну я так сделал):
signtool.exe sign /f "Corp Software.pfx" /p pass -t http://timestamp.verisign.com/scripts/timstamp.dll "$(TargetPath)"

Модули подписаны сертификатом:

Серийный номер: 612D7BF3000000000012
Субъект: E = development@comp.ru CN = COMP Software OU = IT O = EPSA L = SPb S = SPb C = RU
Издатель(Issuer): CN = comp-GWSRV-CA DC = comp DC = local

Корневой сертификат издателя (CA в домене):
Серийный номер: 155AE3A6B2F0D28B47F017A4436019BF
Субъект: CN = comp-GWSRV-CA DC = comp DC = local
Издатель(Issuer): CN = comp-GWSRV-CA DC = comp DC = local

На самоподписанных сертификатах все работает
Например, когда:
Серийный номер: C191A06AD69C89944FDE4D6DB7A86949
Кому выдан: CN = My Corporation
Кем выдан: CN = My Corporation
Все будет замечательно.

Но, если передаю, например:
Серийный номер: 612D7BF3000000000012
Издатель(Issuer): CN = comp-GWSRV-CA,DC = comp,DC = local (запятые ставлю)
Не находит. Пробовал различные комбинации - не находит (
Что не так?

На входе: путь к файлу (dll или exe), Серийный номер, Кем выдан
На выходе: ERROR_SUCCESS - если найден.

Код:

LRESULT CLCertVerifyCertificateW(LPCWSTR pszFilePath, LPCWSTR pszSerialNumber, LPCWSTR pszIssuer){
	if(!pszFilePath || !pszSerialNumber || !pszIssuer) return ERROR_BAD_ARGUMENTS;
		
	BOOL			lResult=ERROR_ACCESS_DENIED;

	HCRYPTPROV		hCryptProvider=NULL;
	
	DWORD			dwEncoding=0x00;
	DWORD			dwContent=0x00;
	DWORD			dwFormatType=0x00;
	HCRYPTMSG		hCryptMsg=NULL;
	HCERTSTORE		hCertStore=NULL;

	PCCERT_CONTEXT	pSignerCert=NULL;

	CERT_ID			cert_id={0x00};
	LPBYTE			pbtIssure=NULL;
	DWORD			dwIssureLen=0x00;
	LPBYTE			pbtSerialNumber=NULL;
	DWORD			dwSerialNumberLen=0x00;
	
	WCHAR			pszAlphaHex[0x03]={0x00};
	PWCHAR			pszSerialNumberTmp=NULL;
	LPBYTE			pbtSerialNumberTmp=NULL;
	

    // Get context to use for Crypt
    if(::CryptAcquireContextW(&hCryptProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){
	    
		// Open file store
		if(::CryptQueryObject(CERT_QUERY_OBJECT_FILE, pszFilePath, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0x00, &dwEncoding, &dwContent, &dwFormatType, &hCertStore, &hCryptMsg, NULL)){

			// Prepare cert info for search in app file
			// Convert Issuer
			if(::CertStrToNameW(dwEncoding, pszIssuer, CERT_NAME_STR_COMMA_FLAG | CERT_X500_NAME_STR | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG, NULL, NULL, &dwIssureLen, NULL)){
				
				pbtIssure=new BYTE[dwIssureLen]();
				if(pbtIssure){
					if(::CertStrToNameW(dwEncoding, pszIssuer, CERT_NAME_STR_COMMA_FLAG | CERT_X500_NAME_STR | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG, NULL, pbtIssure, &dwIssureLen, NULL)){
						
						cert_id.IssuerSerialNumber.Issuer.pbData=pbtIssure;
						cert_id.IssuerSerialNumber.Issuer.cbData=dwIssureLen;

						// Convert SerialNumber (from hex string to byte with reverse order)
						dwSerialNumberLen=wcslen(pszSerialNumber);
						if(dwSerialNumberLen && !(dwSerialNumberLen%0x02)){
	
							pszSerialNumberTmp=(PWCHAR)(pszSerialNumber+dwSerialNumberLen);
							dwSerialNumberLen=dwSerialNumberLen/0x02;

							pbtSerialNumber=new BYTE[dwSerialNumberLen]();
							if(pbtSerialNumber){
								pbtSerialNumberTmp=pbtSerialNumber;
	
								while(pszSerialNumber<pszSerialNumberTmp){
									pszSerialNumberTmp-=0x02;
									memcpy(pszAlphaHex, pszSerialNumberTmp, 0x04);

									*pbtSerialNumberTmp=(BYTE)std::stoi(pszAlphaHex, 0x0, 0x10);
									pbtSerialNumberTmp++;
								}
	 
								cert_id.dwIdChoice=CERT_ID_ISSUER_SERIAL_NUMBER;
								cert_id.IssuerSerialNumber.SerialNumber.pbData=pbtSerialNumber;
								cert_id.IssuerSerialNumber.SerialNumber.cbData=dwSerialNumberLen;

								// Search certificate in this store
								pSignerCert=::CertFindCertificateInStore(hCertStore, dwEncoding, 0x00, CERT_FIND_CERT_ID, &cert_id, NULL);
								if(pSignerCert) lResult=ERROR_SUCCESS;
							}
						}
					}
				}
			}
		}			
	}

	// Cleanup
	if(pbtSerialNumber)	delete pbtSerialNumber;
	if(pbtIssure)		delete pbtIssure;
    if(pSignerCert)		::CertFreeCertificateContext(pSignerCert);
    if(hCryptMsg)		::CryptMsgClose(hCryptMsg);
    if(hCertStore)		::CertCloseStore(hCertStore, 0x00);
	if(hCryptProvider)	::CryptReleaseContext(hCryptProvider, 0x00);
	
	return lResult;

}

Отредактировано пользователем 27 мая 2016 г. 9:51:48(UTC)  | Причина: Не указана

Offline Kirill Sobolev  
#2 Оставлено : 27 мая 2016 г. 10:30:57(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,733
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 177 раз в 168 постах
cert_id.IssuerSerialNumber.Issuer после заполнения совпадает с Issuer сертификата?
Техническую поддержку оказываем тут
Наша база знаний
Offline yndtrud  
#3 Оставлено : 27 мая 2016 г. 10:52:14(UTC)
yndtrud

Статус: Участник

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

Сказал(а) «Спасибо»: 2 раз
Серийный номер: 612D7BF3000000000012
Субъект: E = development@comp.ru CN = COMP Software OU = IT O = EPSA L = SPb S = SPb C = RU
Издатель(Issuer): CN = epsa-GWSRV-CA DC = epsa DC = local


Передаю в функцию:
pszSerialNumber=L"612D7BF3000000000012"
pszIssuer=L"CN = epsa-GWSRV-CA,DC = epsa,DC = local"

Вот выглядит в дебагере после обрабоки
https://fotki.yandex.ru/next/users/kristy80/album/509450/view/1521260
Offline Kirill Sobolev  
#4 Оставлено : 27 мая 2016 г. 11:16:31(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,733
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 177 раз в 168 постах
А сам сертификат можете выложить?
Техническую поддержку оказываем тут
Наша база знаний
Offline yndtrud  
#5 Оставлено : 27 мая 2016 г. 12:23:07(UTC)
yndtrud

Статус: Участник

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

Сказал(а) «Спасибо»: 2 раз
Да, они для теста сделаны.

Отредактировано пользователем 27 мая 2016 г. 15:35:17(UTC)  | Причина: Не указана

Offline yndtrud  
#6 Оставлено : 27 мая 2016 г. 13:48:14(UTC)
yndtrud

Статус: Участник

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

Сказал(а) «Спасибо»: 2 раз
Забавано. Написал вот так: DC=local,DC=epsa,CN=epsa-GWSRV-CA и всё нормально! В чем прикол?
Offline Kirill Sobolev  
#7 Оставлено : 27 мая 2016 г. 14:16:22(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,733
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 177 раз в 168 постах
Прикол в том, что компоненты имени в окне просмотра отображаются в обратном порядке.
Вы можете добавить флаг CERT_NAME_STR_REVERSE_FLAG в вызов CertStrToName.
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Кирилл Соболев за этот пост.
yndtrud оставлено 27.05.2016(UTC)
Offline yndtrud  
#8 Оставлено : 27 мая 2016 г. 15:34:44(UTC)
yndtrud

Статус: Участник

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

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