Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.06.2013(UTC) Сообщений: 83  Откуда: Москва Сказал(а) «Спасибо»: 16 раз Поблагодарили: 1 раз в 1 постах
|
Есть клиент и сервер. Клиент - карта, Сервер - программа исользующая КриптоПро CSP. Карта шифрует данные (длина данных не кратна длине блока) по ГОСТ28147 в режиме CFB (выравнивание не требуется, карта его не делает). По открытым данным карта вычисляет имитовставку. Предварительно делая выравнивание по такому алгоритму: Цитата: static void Align(unsigned char * data, int dsz, unsigned char ** data_aligned, int * asz){ *asz = dsz; if(dsz <= 8) *asz = 16; else if(dsz%8) *asz = dsz+(8-dsz%8); *data_aligned = (unsigned char*)malloc(*asz); memset(*data_aligned, 0, *asz); memcpy(*data_aligned, data, dsz); if(dsz <= 8) memcpy(*data_aligned+8, data, dsz); }
Пакет приходит на сервер, где производится расшифрование пакета с проверкой имитовставки в один вызов КриптоПро: Цитата: //расшифровать данные и вычислить имиту в одно действие //в случае успешного выполнения возвращает 1, в случае ошибки - 0 static int DecryptImit(HCRYPTPROV * phProv, HCRYPTKEY * phKey, LPBYTE pbIn, DWORD dwInLen, LPBYTE pbOut, DWORD dwOutLen){ DWORD dwLen, dwMode; HCRYPTHASH hHash = 0; BYTE * data = NULL; dwLen=dwInLen; data = (BYTE *)malloc(dwLen); if(!data){ err_msg(__FILE__, __FUNCTION__, __LINE__,NULL); return 0; } memcpy(data,pbIn,dwInLen);//SV плюс зашифрованные данные с имитой по ним dwMode = CRYPT_MODE_CFB; if(!CryptSetKeyParam(*phKey, KP_MODE, (BYTE*)&dwMode, 0)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } dwMode = ZERO_PADDING; if(!CryptSetKeyParam(*phKey, KP_PADDING, (BYTE*)&dwMode, 0)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } if(!CryptCreateHash(*phProv, CALG_G28147_IMIT, *phKey, 0, &hHash)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } if(!CryptDecrypt(*phKey, hHash, TRUE, CP_CHP(CP_CHP_IV_USER|CP_CHP_HASH_ENCRYPT|CP_CHP_HASH_PACKET,0,0,1), data, &dwLen)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } if(hHash)CryptDestroyHash(hHash); memcpy(pbOut,&data[SEANCE_VECTOR_LEN],dwOutLen); //расшифрованные данные free(data); return 1; }
Вызывается так: Цитата: memcpy(pbIn,iv,8); memcpy(&pbIn[8],data,DATA_LEN); memcpy(&pbIn[8+DATA_LEN],imit,4); if(!DecryptImit(&hProvClient, &hSessionKey, pbIn, 8+DATA_LEN+4, pbOut, DATA_LEN))goto end;
Далее сервер формирует ответный пакет клиенту, в котором содержится шифротекст и имита, полученные за один вызов КриптоПро: Цитата: //зашифровать данные и вычислить имиту в одно действие //в случае успешного выполнения возвращает 1, в случае ошибки - 0 static int CryptImit(HCRYPTPROV * phProv, HCRYPTKEY * phKey, LPBYTE pbIn, DWORD dwInLen, LPBYTE pbOut, DWORD dwOutLen){ DWORD dwLen, dwMode; HCRYPTHASH hHash = 0; BYTE * data = NULL; dwLen=dwInLen; //inout буфер: на входе - iv, data, <место под имиту>, на выходе: iv(мусор), шифротекст, имита data = (BYTE *)malloc(dwLen); if(!data){ err_msg(__FILE__, __FUNCTION__, __LINE__,NULL); return 0; } memcpy(data,pbIn,dwInLen-EXPORT_IMIT_SIZE); //имиты на входе нет, есть только место под неё dwMode = CRYPT_MODE_CFB; if(!CryptSetKeyParam(*phKey, KP_MODE, (BYTE*)&dwMode, 0)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } dwMode = ZERO_PADDING; if(!CryptSetKeyParam(*phKey, KP_PADDING, (BYTE*)&dwMode, 0)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } if(!CryptCreateHash(*phProv, CALG_G28147_IMIT, *phKey, 0, &hHash)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } if(!CryptEncrypt(*phKey, hHash, TRUE, CP_CHP(CP_CHP_IV_USER|CP_CHP_HASH_ENCRYPT|CP_CHP_HASH_PACKET,0,0,1), data, &dwLen, dwLen)){ free(data); err_msg(__FILE__, __FUNCTION__, __LINE__," (error: 0x%x)\n", GetLastError()); return 0; } if(hHash)CryptDestroyHash(hHash); memcpy(pbOut,&data[SEANCE_VECTOR_LEN],dwOutLen); //зашифрованные данные и имита по ним free(data); return 1; }
Вызывается так: Цитата: memcpy(pbIn,iv,8); memcpy(&pbIn[8],data,DATA_LEN); if(!DecryptImit(&hProvClient, &hSessionKey, pbIn, 8+DATA_LEN+4, pbOut, DATA_LEN+4))goto end;
Если в обмене участвуют данные, длина которых кратна длине блока, то все работает. Если в обмене участвуют данные, длина которых не кратна длине блока, то: 1) если длина данных меньше дины блока (<8 байт), то выдается ошибка NTE_BAD_HASH, 0x80090002, 2) если длина данных больше длины блока, то всё работает. У нас на клиенте (на карте), при вычислении имитовставки, если данные имеют длину меньше длины блока, то при выравнивании блок дополняется нулями и задваивается. Правильно ли я понимаю, что: 1) В КриптоПро такого "задваивания" как у нас (в случае если длина данных меньше длины блока) не производится (т.е. результатом выравнивания будет один блок дополненный нулями)? 2) Алгоритм подобный приведенному выше (функция Align) в КриптоПро не поддерживается ? Отредактировано пользователем 26 июня 2015 г. 12:34:05(UTC)
| Причина: уточнил суть вопроса
|