Статус: Участник
Группы: Участники
Зарегистрирован: 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))
....... (очистка, проверки - пропустил) ...........
|