Крипто-Про CSP |
//-------------------------------------------------------------------- // Пример кода, в котором описан процесс зашифрования драйвером // сообщения, на основе информации, полученной от пользователя. // В данной программе от пользователя получен пакет, в котором содержится // следующая информация: // - длина открытого ключа пользователя // - открытый ключ пользователя // - длина BLOBа для инициализации ДСЧ // - BLOB для инициализации ДСЧ // - длина BLOBа для хранения параметра KP_DHOID // - BLOB для хранения параметра KP_DHOID // Вся эта информация передается через InputBuffer. // // В действительности процесс расшифрования можно разбить на 3 основные части: // - Инициализация контекста. Для этой части необходимо, чтобы отправителем // сообщения являлся CSP. Для каждого получателя инициализация контектса // осуществляется один раз, после чего может проводится обмен пакетами // с отправителем. // // - Получение Agree ключа с другой стороной (с отправителем). Для этой части // отправителем может быть не только CSP, но и драйвер. Для каждого получателя // эта часть процесса осуществляется один раз. // // - Собственно зашифрование сообщения. Для каждого сообщения эта часть // процесса осуществляется заново (после того, как Agree ключи согласованы, // обмен пакетами может производиться любое число раз). //-------------------------------------------------------------------- NTSTATUS Encrypt( PCHAR inBuf, ULONG inBufLength, PCHAR outBuf, ULONG *outBufLength ) { //-------------------------------------------------------------------- // Объявление и инициализация переменных. CRYPT_UINT_BLOB BLOB; VTABLEPROVSTRUC VTable; HCRYPTPROV hProv; // Дескриптор CSP DWORD keyLen = 0; // Длина BLOBа открытого ключа пользователя DWORD RNGLen = 0; // Длина BLOBа ДСЧ DWORD ParamLenD = 0; // Длина BLOBа для хранения параметра KP_DHOID BYTE* ParamD ; // BLOB для хранения параметра KP_DHOID BYTE* keyBLOB; // BLOB открытого ключа пользователя BYTE* RNGBLOB; // BLOB ДСЧ BYTE *pbKeyBlobSimple; // Указатель на сессионный ключевой BLOB DWORD dwBlobLenSimple = 0; // Длина сессионного ключевого BLOBа BYTE *pbKeyBlob; // Указатель на BLOB открытого ключа драйвера DWORD dwBlobLen = 0; // Длина BLOBа открытого ключа драйвера BYTE *pbParamBlob; // Указатель на BLOB для передачи параметра KP_CIPHEROID DWORD dwParamBlobLen = 0; // Длина BLOBа для передачи параметра KP_CIPHEROID HCRYPTKEY hDriverKey; // Дескриптор открытого ключа драйвера HCRYPTKEY hSessionKey; // Дескриптор сессионного ключа HCRYPTKEY hAgreeKey; // Дескриптор ключа согласования BYTE *pbIV = NULL; // Вектор инициализации сессионного ключа DWORD dwIV = 0; // Длина вектора инициализации BYTE pbContent[100] = { "Security is our business." }; // Сообщение DWORD cbContent = (DWORD)(strlen((char *)pbContent)+1); // Длина сообщения DWORD bufLen = sizeof(pbContent); // Длина буфера //-------------------------------------------------------------------- // Часть 1 - получение контекста. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Заполнение таблицы. Необходимо для корректной работы провайдера. VTable.Version = 3; VTable.dwProvType = 75; VTable.pszProvName = "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider"; VTable.cbContextInfo = 0; VTable.pbContextInfo = NULL; VTable.FuncReturnhWnd = &FunReturnHWnd; VTable.FuncVerifyImage = &FunVerifyImage; //-------------------------------------------------------------------- // Получение дескриптора провайдера без доступа к закрытым ключам. if(CPAcquireContext( &hProv, NULL, CRYPT_VERIFYCONTEXT, &VTable )) { CPIOCTL_KDPRINT(("CPAcquireContext succeeded.\n")); } else { CPIOCTL_KDPRINT(("Error: CPAcquireContext Failed.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Получение BLOBа открытого ключа пользователя, BLOBа ДСЧ, BLOBов для // хранения параметров ключа пользователя и их длин из InputBuffer. memcpy(&keyLen, inBuf, sizeof(DWORD)); keyBLOB = (BYTE*)ExAllocatePoolWithTag( PagedPool, keyLen, CPTEST_POOL ); memcpy(keyBLOB, inBuf + sizeof(DWORD), keyLen); memcpy(&RNGLen, inBuf + sizeof(DWORD) + keyLen, sizeof(DWORD)); RNGBLOB = (BYTE*)ExAllocatePoolWithTag( PagedPool, RNGLen, CPTEST_POOL ); memcpy(RNGBLOB, inBuf + 2*sizeof(DWORD) + keyLen, RNGLen); memcpy(&ParamLenD, inBuf + 2*sizeof(DWORD) + keyLen + RNGLen, sizeof(DWORD)); ParamD = (BYTE*)ExAllocatePoolWithTag( PagedPool, ParamLenD, CPTEST_POOL ); memcpy(ParamD, inBuf + 3*sizeof(DWORD) + keyLen + RNGLen, ParamLenD); //-------------------------------------------------------------------- // Установка параметра PP_RANDOM. Необходимо для корректной работы // провайдера (инициализация ДСЧ). BLOB.cbData = RNGLen; BLOB.pbData = RNGBLOB; if(CPSetProvParam( hProv, PP_RANDOM, (BYTE*)&BLOB, 0)) { CPIOCTL_KDPRINT(("CPSetProvParam succeeded.\n")); } else { CPIOCTL_KDPRINT(("Error: CPSetProvParam Failed.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Подготовка эфемерного ключа драйвера. if(CPGenKey( hProv, CALG_DH_EL_EPHEM, CRYPT_PREGEN, &hDriverKey)) { CPIOCTL_KDPRINT(("Created a ephemeral driver key.\n")); } else { CPIOCTL_KDPRINT(("Error: CPGenKey Failed.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Установка параметра KP_DHOID (согласование с CSP). // По умолчанию драйвер работает на наборе параметров 1.2.643.2.2.35.1. // Без установки параметра KP_DHOID программа будет неверно работать, // если параметры алгоритма Диффи-Хелмана не будут являться параметрами // по умолчанию. if(CPSetKeyParam( hProv, hDriverKey, KP_DHOID, ParamD, 0)) { CPIOCTL_KDPRINT(("The parameters have been set. \n")); } else { CPIOCTL_KDPRINT(("Error during SetKeyParam.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Генерация эфемерного ключа (с установленным параметром KP_DHOID). if(CPSetKeyParam( hProv, hDriverKey, KP_X, NULL, 0)) { CPIOCTL_KDPRINT(("The key is generated. \n")); } else { CPIOCTL_KDPRINT(("Error during SetKeyParam.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Часть 2 - получение ключа согласования. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Получение ключа согласования импортом открытого ключа пользователя // на открытом ключе драйвера. if (CPImportKey( hProv, keyBLOB, keyLen, hDriverKey, 0, &hAgreeKey)) { CPIOCTL_KDPRINT(("The Agree key has been acquired. \n")); } else { CPIOCTL_KDPRINT(("Error: CPImportKey Failed.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Передача параметра KP_CIPHEROID ключа согласования. // По умолчанию CSP работает на наборе параметров 1.2.643.2.2.31.1. // Без установки параметра KP_CIPHEROID программа будет неверно работать, // если параметры шифрования для CSP не будут являться параметрами по умолчанию. //-------------------------------------------------------------------- // Определение размера BLOBа и распределение памяти. if(CPGetKeyParam( hProv, hAgreeKey, KP_CIPHEROID, NULL, &dwParamBlobLen, 0)) { CPIOCTL_KDPRINT(("Size of the BLOB determined. \n")); } else { CPIOCTL_KDPRINT(("Error computing BLOB length.")); return STATUS_UNSUCCESSFUL; } pbParamBlob = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwParamBlobLen, CPTEST_POOL ); if(pbParamBlob) { CPIOCTL_KDPRINT(("Memory has been allocated for the pbParamBlob. \n")); } else { CPIOCTL_KDPRINT(("Out of memory. \n")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Копирование параметров ключа в pbParamBlob. if(CPGetKeyParam( hProv, hAgreeKey, KP_CIPHEROID, pbParamBlob, &dwParamBlobLen, 0)) { CPIOCTL_KDPRINT(("Parameters have been written to the pbParamBlob. \n")); } else { CPIOCTL_KDPRINT(("Error during CPGetKeyParam.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Получение сессионного ключа драйвера. if(CPGenKey( hProv, CALG_G28147, CRYPT_EXPORTABLE, &hSessionKey)) { CPIOCTL_KDPRINT(("Created a session driver key.\n")); } else { CPIOCTL_KDPRINT(("Error: CPGenKey Failed.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Экспортирование сессионного ключа на ключе Agree в SIMPLEBLOB. // //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера BLOBа сессионного ключа и распределение памяти. if(CPExportKey( hProv, hSessionKey, hAgreeKey, SIMPLEBLOB, 0, NULL, &dwBlobLenSimple)) { CPIOCTL_KDPRINT(("Size of the BLOB for the session key determined. \n")); } else { CPIOCTL_KDPRINT(("Error computing BLOB length.")); return STATUS_UNSUCCESSFUL; } pbKeyBlobSimple = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwBlobLenSimple, CPTEST_POOL ); if(pbKeyBlobSimple) { CPIOCTL_KDPRINT(("Memory has been allocated for the BLOB. \n")); } else { CPIOCTL_KDPRINT(("Out of memory. \n")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Шифрование сессионного ключа на ключе Agree. if(CPExportKey( hProv, hSessionKey, hAgreeKey, SIMPLEBLOB, 0, pbKeyBlobSimple, &dwBlobLenSimple)) { CPIOCTL_KDPRINT(("Contents have been written to the BLOB. \n")); } else { CPIOCTL_KDPRINT(("Error during CryptExportKey.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Экспортирование открытого ключа драйвера в PUBLICKEYBLOB. // //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера BLOBа открытого ключа и распределение памяти. if(CPExportKey( hProv, hDriverKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) { CPIOCTL_KDPRINT(("Size of the BLOB for the public key determined. \n")); } else { CPIOCTL_KDPRINT(("Error computing BLOB length.")); return STATUS_UNSUCCESSFUL; } pbKeyBlob = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwBlobLen, CPTEST_POOL ); if(pbKeyBlob) { CPIOCTL_KDPRINT(("Memory has been allocated for the BLOB. \n")); } else { CPIOCTL_KDPRINT(("Out of memory. \n")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Экспортирование открытого ключа в BLOB. if(CPExportKey( hProv, hDriverKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) { CPIOCTL_KDPRINT(("Contents have been written to the BLOB. \n")); } else { CPIOCTL_KDPRINT(("Error during CryptExportKey.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Часть 3 - собственно зашифрование. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера вектора инициализации сессионного ключа. if (CPGetKeyParam( hProv, hSessionKey, KP_IV, NULL, &dwIV, 0)) { CPIOCTL_KDPRINT(("Size of the IV for the session key determined. \n")); } else { CPIOCTL_KDPRINT(("Error computing IV length.")); return STATUS_UNSUCCESSFUL; } pbIV = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwIV, CPTEST_POOL ); if (pbIV) { CPIOCTL_KDPRINT(("Memory has been allocated for the IV. \n")); } else { CPIOCTL_KDPRINT(("Out of memory. \n")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Определение вектора инициализации сессионного ключа. if (CPGetKeyParam( hProv, hSessionKey, KP_IV, pbIV, &dwIV, 0)) { CPIOCTL_KDPRINT(("CPGetKeyParam succeeded. \n")); } else { CPIOCTL_KDPRINT(("Error during CPGetKeyParam.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Зашифрование исходного сообщения. if(CPEncrypt( hProv, hSessionKey, 0, TRUE, 0, pbContent, &cbContent, bufLen)) { CPIOCTL_KDPRINT(("CPEncrypt succeeded. \n")); } else { CPIOCTL_KDPRINT(("Error during CPEncrypt.")); return STATUS_UNSUCCESSFUL; } //-------------------------------------------------------------------- // Определение длины OutputBuffer и запись в него следующей информации: // - длина BLOBа открытого ключа драйвера // - BLOB открытого ключа драйвера // - длина BLOBа сессионного ключа драйвера // - BLOB сессионного ключа драйвера // - длина вектора инициализации // - вектор инициализации // - длина зашифрованного сообщения // - зашифрованное сообщение // - длина BLOBа для перечачи параметра KP_CIPHEROID // - BLOB для перечачи параметра KP_CIPHEROID. *outBufLength = 5*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV + cbContent + dwParamBlobLen; memcpy(outBuf, &dwBlobLen, sizeof(DWORD)); memcpy(outBuf + sizeof(DWORD), pbKeyBlob, dwBlobLen); memcpy(outBuf + sizeof(DWORD) + dwBlobLen, &dwBlobLenSimple, sizeof(DWORD)); memcpy(outBuf + 2*sizeof(DWORD) + dwBlobLen, pbKeyBlobSimple, dwBlobLenSimple); memcpy(outBuf + 2*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple, &dwIV, sizeof(DWORD)); memcpy(outBuf + 3*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple, pbIV, dwIV); memcpy(outBuf + 3*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV, &cbContent, sizeof(DWORD)); memcpy(outBuf + 4*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV, pbContent, cbContent); memcpy(outBuf + 4*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV + cbContent, &dwParamBlobLen, sizeof(DWORD)); memcpy(outBuf + 5*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV + cbContent, pbParamBlob, dwParamBlobLen); // Вся эта информация передается пакетом пользователю для расшифрования сообщения. // Уничтожение дескриптора открытого ключа. if(hDriverKey) CPDestroyKey(hProv, hDriverKey); // Уничтожение дескриптора сессионного ключа. if(hSessionKey) CPDestroyKey(hProv, hSessionKey); // Уничтожение дескриптора ключа согласования. if(hAgreeKey) CPDestroyKey(hProv, hAgreeKey); // Освобождение дескриптора провайдера. if(hProv) CPReleaseContext(hProv, 0); // Освобождение памяти. ExFreePool( pbIV ); ExFreePool( pbKeyBlob ); ExFreePool( pbKeyBlobSimple ); ExFreePool( keyBLOB ); ExFreePool( RNGBLOB ); ExFreePool( ParamD ); ExFreePool( pbParamBlob ); return STATUS_SUCCESS; } // Конец Encrypt
Ядро Windows 2000/XP/2003: Необходимо Windows 2000 SP4
или старше с Internet Explorer 6.0 или старше.
Ядро Windows NT/95/98/ME: CSP 3.0 не поддерживает (см.
КриптоПро CSP
2.0 ).
Ядро Solaris: 9 Update 4 или выше.
Ядро FreeBSD: FreeBSD 5.2 или выше
Ядро Linux: RedHat 7.3, RedHad 9.0.
Что Вы
думаете по поводу данной статьи? |
Закажите CD c Крипто-Про CSP |