| ||||
| ||||
Насколько я понял, ГОСТ28147 не должен поддерживать режим CBC (в ГОСТ он просто не описан). В CryptoPro CBC реализован (CryptSetKeyParam работает), как это согласуется с ГОСТ ? | ||||
Ответы: | ||||
| ||||
В ГОСТ 28147, вообще говоря, не описаны ни ECB, ни CFB, ни OFB(CNT). Речь может идти только о аналогичных режимах. CBC в провайдере КриптоПро CSP реализован как в CBC на DES преобразовании. Режим блочный. Зашифрование. На 0 шаг блок зацепления передается извне. На i-шаге (i>=0) 1. извлекается i-й блок данных; 2. побитово складывается с блоком зацепления; 3. подается на шифратор ГОСТ 28147 4. выход шифратора -> шифрованный i-й блок. 5. выход шифратора -> блок зацепления Расшифрование: на 0 шаг блок зацепления(0) передается извне. для i-го шага: 1. считывается i-й блок данных 2. блок зацепления(1) <- i-й блок данных 3. i-й блок подается на дешифратор ГОСТ 28147 4. выход шифратора побитово складывается с блоком зацепления(0) 5. i-й блок расшированных данных <-результат сложения 6. блок зацепления(0)<-блок зацепления(1) примерно так :) | ||||
| ||||
Еще один вопрос про CBC - не могу получить IV: ::CryptGetKeyParam(hKey, KP_IV, pIV, &nLen, 0) возвращает случайный вектор. Если поменять провайдер и алгоритм на MS AES, то код работает. | ||||
| ||||
P_IV работает в этой функции для сессионного ключа (параметр CALG_G28147). Иначе генерировать вектор следует функцией CPGenRandom(). | ||||
| ||||
Мне не надо генерировать случайные числа, мне просто надо получить IV:) Приведенный код должен возвращать IV = {0, 1, 2, 3, 4, 5, 6, 7}, а возвращает мусор: HCRYPTPROV hProv; //::CryptAcquireContext(&hProv, NULL, NULL, PROV_GOST_2001_DH, CRYPT_VERIFYCONTEXT); ::CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); HCRYPTKEY hKey; //::CryptGenKey(hProv, CALG_G28147, 0, &hKey); ::CryptGenKey(hProv, CALG_DES, 0, &hKey); DWORD mode = CRYPT_MODE_CBC; ::CryptSetKeyParam(hKey, KP_MODE, (PBYTE)&mode, 0); BYTE iv[8] = {0, 1, 2, 3, 4, 5, 6, 7}; ULONG len = 8; ::CryptSetKeyParam(hKey, KP_IV, iv, 0); char buf[16] = {0}; len = 8; ::CryptEncrypt(hKey, NULL, TRUE, 0, (PBYTE)buf, &len, 16); len = 8; ::CryptGetKeyParam(hKey, KP_IV, iv, &len, 0); | ||||
| ||||
Разумеется, так и было задумано. Значение инитвектора меняется при каждом использовании ключа. Поэтому, перед зашифрованием и перед расшифрованием нужно устанавливать IV. Или: перед зашифрованием получать IV (GetKeyParam), сохранять его, а перед расшифрованием устанавливать. | ||||
| ||||
OK, т.е. CryptGetKeyParam возвращает не IV, а _текущий_ IV - но ведь это не совпадает с поведением провайдеров от MS? | ||||