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

Уведомление

Icon
Error

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

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

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

Сказал(а) «Спасибо»: 2 раз
Думаю последний раз, когда я потревожу форум.

Осталось решить одну внезапную для новичка в CryptoAPI проблему:

Хочу зашифровать/расшифровать данные.
Если создать сессионный ключ, то код прекрасно работает. Могу экспортировать этот ключ, импортировать и все так же работает.
Понятно, что это не самый лучший вариант и я реализовал шифрование по паролю. Возникла странная проблема.

Как я делаю.
Беру пароль, перевожу его в ANSI из UNICODE (ну это не важно, но удобно)
Инициализирую Хэш на основе SHA1
if(::CryptCreateHash(hCryptProvider, CALG_SHA1, NULL, 0x00, &hCryptHash))
Передаю ему мой пароль в ANSI минус \0 у стринга
if(::CryptHashData(hCryptHash, (LPBYTE)pszPassword, dwPasswordLength-0x01, 0x00))
Создаю ключ. Симметричный 3DES с солью на основе моего хэша.
if(::CryptDeriveKey(hCryptProvider, CALG_3DES, hCryptHash, CRYPT_CREATE_SALT, phCryptKey)){
Ну и использую его.

Вот проблема:
Например, мой пароль: MyPass$66
Шифрую, расшифровываю - все нормально.
Но, если я заменю пароль на MyPas1234 (то есть наберу любые символы в пароле - а именно не более 50% длинны его на конце), то он также спокойно расшифровывает данные!
Что за ерунда? Не более половины и именно в конце пароля - могут быть любые? Что я делаю не так? Длинна может быть любая, например 30 - символов - тогда 15 будут заменяемыми



Выдержка кода по генерации ключа для пароля.
Код:


// Функция шифрования
LRESULT CLCryptEncryptByPasswordW(const LPVOID pSrc, DWORD dwSrcSize, LPBYTE* ppbtDst, PDWORD pdwDstSize, LPCWSTR pszPassword){
	if(!pszPassword) return ERROR_BAD_ARGUMENTS;


	LRESULT			lResult			=ERROR_INTERNAL_ERROR;
	HCRYPTPROV		hCryptProvider		=NULL;
	HCRYPTKEY		hCryptKey		=NULL;


	// Get private key from password and crypt
	if(::CryptAcquireContextW(&hCryptProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){
		lResult=CLCryptGetPrivateKey(hCryptProvider, pszPassword, &hCryptKey);		
		if(lResult==ERROR_SUCCESS)
			lResult=CLCryptEncrypt(pSrc, dwSrcSize, ppbtDst, pdwDstSize, hCryptKey);
	}


....... (очистка, проверки - пропустил) ...........



// Генерация ключа из пароля
LRESULT CLCryptGetPrivateKey(HCRYPTPROV hCryptProvider, LPCWSTR pszPassword, HCRYPTKEY* phCryptKey){
	if(!hCryptProvider || !pszPassword || !phCryptKey) return ERROR_BAD_ARGUMENTS;


	LRESULT			lResult			=ERROR_INTERNAL_ERROR;
	HCRYPTHASH		hCryptHash		=NULL;
	LPSTR			pszPasswordA		=NULL;
	DWORD			dwPasswordLength	=0x00;


	// Convert to ANSI
	dwPasswordLength=wcslen(pszPassword)+0x01;
	pszPasswordA=(LPSTR)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY,  dwPasswordLength);
	if(pszPasswordA){	
		if(::WideCharToMultiByte(CP_ACP, 0x00, pszPassword, dwPasswordLength, pszPasswordA, dwPasswordLength, NULL, NULL)){
			// Get hash
			if(::CryptCreateHash(hCryptProvider, CALG_SHA1, NULL, 0x00, &hCryptHash)){
				if(::CryptHashData(hCryptHash, (LPBYTE)pszPassword, dwPasswordLength-0x01, 0x00)){
					// Create private key from hash
					if(::CryptDeriveKey(hCryptProvider, CALG_3DES, hCryptHash, CRYPT_CREATE_SALT, phCryptKey)){
						lResult=ERROR_SUCCESS;
					}
				}
			}
		}
	}
	else
		lResult=ERROR_OUTOFMEMORY;

....... (очистка, проверки - пропустил) ...........


// Само шифрование
LRESULT CLCryptGetPrivateKey(HCRYPTPROV hCryptProvider, LPCWSTR pszPassword, HCRYPTKEY* phCryptKey){
	if(!hCryptProvider || !pszPassword || !phCryptKey) return ERROR_BAD_ARGUMENTS;

....... (выделение памяти и подобное пропустил) ...........

	if(::CryptEncrypt(hCryptKey, NULL, TRUE, 0x00, *ppbtDst, &dwSrcSize, *pdwDstSize) && (dwSrcSize==*pdwDstSize))

....... (очистка, проверки - пропустил) ...........

Offline Kirill Sobolev  
#2 Оставлено : 2 июня 2016 г. 16:05:12(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Вы в CryptHashData передаете (LPBYTE)pszPassword - это LPCWSTR, при этом указываете размер dwPasswordLength-0x01, т.е. как раз половина, с учетом того что каждый символ - это 2 байта.
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Кирилл Соболев за этот пост.
yndtrud оставлено 02.06.2016(UTC)
Offline yndtrud  
#3 Оставлено : 2 июня 2016 г. 16:38:46(UTC)
yndtrud

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

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

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