//-------------------------------------------------------------------- // В данном примере реализовано копирование закрытого ключа AT_KEYEXCHANGE. // Копирование ключа AT_SIGNATURE производится аналогично. Необходимо также // произвести копирование соответствующих этим ключам сертификатов. // Для корректной работы этой программы копируемые ключи должны быть // созданы как exportable. Копирование ключа производится из контейнера // с именем "Source" (который, соответственно, должен быть создан) в // создаваемый контейнер с именем "Destination" (который, если он имеется, // до начала работы программы должен быть удален). //-------------------------------------------------------------------- static void HandleError(char *s); static void CleanUp(void); static HCRYPTPROV hProvResponder = 0; // Дескриптор CSP получателя static HCRYPTPROV hProvSender = 0; // Дескриптор CSP отправителя static HCRYPTKEY hSenderKey = 0; // Дескриптор копирумого ключа AT_EXCHANGE static HCRYPTKEY hResponderKey = 0; // Дескриптор полученного ключа AT_EXCHANGE static HCRYPTKEY hSenderEphemKey = 0; // Дескриптор эфемерного ключа для отправителя static HCRYPTKEY hResponderEphemKey = 0; // Дескриптор эфемерного ключа для получателя static HCRYPTKEY hSenderAgreeKey = 0; // Дескриптор ключа согласования отправителя static HCRYPTKEY hResponderAgreeKey = 0; // Дескриптор ключа согласования получателя static BYTE *pbKeyBlob = NULL; // Указатель на ключевой BLOB int main (void) { //-------------------------------------------------------------------- // Объявление и инициализация переменных. DWORD dwProvType = PROV_GOST_2012_256; // Тип провайдера по умолчанию DWORD data_len = 0; // Длина буфера BYTE *oid = NULL; // Буфер для хранения параметров DWORD dwBlobLen = 0; // Длина ключевого BLOBа DWORD cAlg = CALG_PRO12_EXPORT; //-------------------------------------------------------------------- // Получение дескриптора контейнера, в который осуществляется копирование // ключа (получатель). if(CryptAcquireContext( &hProvResponder, #ifdef _WIN32 _TEXT("Destination"), #else _TEXT("\\\\.\\HDIMAGE\\Destination"), #endif NULL, dwProvType, CRYPT_NEWKEYSET)) { printf("The responder key container has been acquired. \n"); } else { HandleError("Error during CryptAcquireContext."); } //-------------------------------------------------------------------- // Получение дескриптора контейнера, из которого осуществляется копирование // ключа (отправитель). if(CryptAcquireContext( &hProvSender, _TEXT("Source"), NULL, dwProvType, 0)) { printf("The sender key container has been acquired. \n"); } else { HandleError("Error during CryptAcquireContext."); } //-------------------------------------------------------------------- // Копирование параметров контейнера-отправителя в контейнер-получатель // для параметра PP_HASHOID. //-------------------------------------------------------------------- // Определение размера буфера и распределение памяти. if(CryptGetProvParam( hProvSender, PP_HASHOID, NULL, &data_len, 0)) { printf("Size of the buffer determined. \n"); } else { HandleError("Error computing buffer length."); } oid = (BYTE *)malloc( data_len ); if( !oid ) HandleError("Out of memory. \n"); //-------------------------------------------------------------------- // Копирование параметров контейнера-отправителя в буфер. if(CryptGetProvParam( hProvSender, PP_HASHOID, oid, &data_len, 0)) { printf("Parameters have been written to the buffer. \n"); } else { HandleError("Error during CryptGetProvParam."); } //-------------------------------------------------------------------- // Установка параметров, находящихся в буфере, получателем. if(CryptSetProvParam( hProvResponder, PP_HASHOID, oid, 0 )) { printf("The parameters have been set. \n"); } else { free( oid ); HandleError("Error during CryptSetProvParam."); } //-------------------------------------------------------------------- // Освобождение памяти, используемой буфером. free( oid ); // Обнуление длины буфера для повторного использования. data_len = 0; //-------------------------------------------------------------------- // Копирование параметров контейнера-отправителя в контейнер-получатель // для параметра PP_CIPHEROID. //-------------------------------------------------------------------- // Определение размера буфера и распределение памяти. if(CryptGetProvParam( hProvSender, PP_CIPHEROID, NULL, &data_len, 0)) { printf("Size of the buffer determined. \n"); } else { HandleError("Error computing buffer length."); } oid = (BYTE *)malloc( data_len ); if( !oid ) HandleError("Out of memory. \n"); //-------------------------------------------------------------------- // Копирование параметров контейнера-отправителя в буфер. if(CryptGetProvParam( hProvSender, PP_CIPHEROID, oid, &data_len, 0)) { printf("Parameters have been written to the buffer. \n"); } else { free( oid ); HandleError("Error during CryptGetProvParam."); } //-------------------------------------------------------------------- // Установка параметров, находящихся в буфере, получателем. if(CryptSetProvParam( hProvResponder, PP_CIPHEROID, oid, 0 )) { printf("The parameters have been set. \n"); } else { free( oid ); HandleError("Error during CryptSetProvParam."); } free( oid ); //-------------------------------------------------------------------- // Получение дескриптора закрытого ключа, который будет скопирован. if(CryptGetUserKey( hProvSender, AT_KEYEXCHANGE, &hSenderKey )) { printf("The sender private key has been acquired. \n"); } else { HandleError("Error during CryptGetUserKey private key."); } //-------------------------------------------------------------------- // Генерация эфемерного ключа в контейнере-отправителе. if(CryptGenKey( hProvSender, CALG_DH_GR3410_12_256_EPHEM, CRYPT_EXPORTABLE, &hSenderEphemKey)) { printf("Ephemeral sender key is created. \n"); } else { HandleError("ERROR -- CryptGenKey."); } //-------------------------------------------------------------------- // Генерация эфемерного ключа в контейнере-получателе. if(CryptGenKey( hProvResponder, CALG_DH_GR3410_12_256_EPHEM, CRYPT_EXPORTABLE | CRYPT_PREGEN, &hResponderEphemKey)) { printf("Ephemeral responder key is created. \n"); } else { HandleError("ERROR -- CryptGenKey."); } //-------------------------------------------------------------------- // Согласование параметра KP_DHOID, вырабатываемого в алгоритме // Диффи-Хелмана. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера BLOBа и распределение памяти. if(CryptGetKeyParam( hSenderEphemKey, KP_DHOID, NULL, &dwBlobLen, 0)) { printf("Size of the BLOB determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory. \n"); //-------------------------------------------------------------------- // Копирование параметров ключа в BLOB. if(CryptGetKeyParam( hSenderEphemKey, KP_DHOID, pbKeyBlob, &dwBlobLen, 0)) { printf("Parameters have been written to the BLOB. \n"); } else { HandleError("Error during CryptGetProvParam."); } //-------------------------------------------------------------------- // Копирование параметров в hResponderEphemKey. if(CryptSetKeyParam( hResponderEphemKey, KP_DHOID, pbKeyBlob, 0)) { printf("The parameters have been set. \n"); } else { HandleError("Error during CryptSetProvParam."); } //-------------------------------------------------------------------- // Освобождение памяти, используемой BLOBом. free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; //-------------------------------------------------------------------- // Генерация ключа if(CryptSetKeyParam( hResponderEphemKey, KP_X, NULL, 0)) { printf("X parameter is generated. \n"); } else { HandleError("Error during CryptSetKeyParam."); } //-------------------------------------------------------------------- // Получение ключа согласования в контейнере - получателе. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера BLOBа эфемерного ключа и распределение памяти. if(CryptExportKey( hSenderEphemKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen )) { printf("Size of the BLOB for the sender ephemeral key determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory. \n"); // Экспортирование эфемерного ключа отправителя в BLOB. if(CryptExportKey( hSenderEphemKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { printf("Contents have been written to the BLOB. \n"); } else { HandleError("Error during CryptExportKey."); } //-------------------------------------------------------------------- // Получение ключа согласования получателя импортом эфемерного ключа отправителя // на эфемерном ключе получателя. if(CryptImportKey( hProvResponder, pbKeyBlob, dwBlobLen, hResponderEphemKey, 0, &hResponderAgreeKey)) { printf("The sender ephemeral key has been imported. \n"); } else { HandleError("Error during CryptImportKey ephemeral key."); } //-------------------------------------------------------------------- // Освобождение памяти, используемой BLOBом. free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; //-------------------------------------------------------------------- // Получение ключа согласования в контейнере - отправителе. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера BLOBа эфемерного ключа и распределение памяти. if(CryptExportKey( hResponderEphemKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen )) { printf("Size of the BLOB for the responder ephemeral key determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory. \n"); // Экспортирование эфемерного ключа получателя в BLOB. if(CryptExportKey( hResponderEphemKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { printf("Contents have been written to the BLOB. \n"); } else { HandleError("Error during CryptExportKey."); } //-------------------------------------------------------------------- // Получение ключа согласования получателя импортом эфемерного ключа получателя // на эфемерном ключе отправителя. if(CryptImportKey( hProvSender, pbKeyBlob, dwBlobLen, hSenderEphemKey, 0, &hSenderAgreeKey)) { printf("The responder ephemeral key has been imported. \n"); } else { HandleError("Error during CryptImportKey ephemeral key."); } //-------------------------------------------------------------------- // Освобождение памяти, используемой BLOBом. free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; //-------------------------------------------------------------------- // Конвертирование ключа согласования в сессионный в контейнере - отправителе. if(CryptSetKeyParam( hSenderAgreeKey, KP_ALGID, (BYTE*)&cAlg, 0 )) { printf("The sender agree key has been converted. \n"); } else { HandleError("Error during CryptSetKeyParam agree key."); } //-------------------------------------------------------------------- // Конвертирование ключа согласования в сессионный в контейнере - получателе. if(CryptSetKeyParam( hResponderAgreeKey, KP_ALGID, (BYTE*)&cAlg, 0 )) { printf("The responder agree key has been converted. \n"); } else { HandleError("Error during CryptSetKeyParam agree key."); } //-------------------------------------------------------------------- // Экспорт копируемого пользовательского ключа на сессионном. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера BLOBа ключа и распределение памяти. if(CryptExportKey( hSenderKey, hSenderAgreeKey, PRIVATEKEYBLOB, 0, NULL, &dwBlobLen )) { printf("Size of the BLOB for the sender key determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory. \n"); // Экспорт копируемого пользовательского ключа на сессионном. if(CryptExportKey( hSenderKey, hSenderAgreeKey, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { printf("Contents have been written to the BLOB. \n"); } else { HandleError("Error during CryptExportKey."); } //-------------------------------------------------------------------- // Получение копируемого ключа импортом пользовательского ключа на ключе // согласования. if(CryptImportKey( hProvResponder, pbKeyBlob, dwBlobLen, hResponderAgreeKey, 0, &hResponderKey)) { printf("The private key has been imported. \n"); } else { HandleError("Error during CryptImportKey private key."); } //-------------------------------------------------------------------- // Освобождение памяти, используемой BLOBом. free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; //-------------------------------------------------------------------- // Копирование параметров ключа hSenderKey в параметры ключа hResponderKey // для KP_CERTIFICATE. //-------------------------------------------------------------------- // Определение размера BLOBа и распределение памяти. if(CryptGetKeyParam( hSenderKey, KP_CERTIFICATE, NULL, &dwBlobLen, 0)) { printf("Size of the BLOB determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(pbKeyBlob) { printf("Memory has been allocated for the BLOB. \n"); } else { HandleError("Out of memory. \n"); } //-------------------------------------------------------------------- // Копирование параметров ключа в BLOB. if(CryptGetKeyParam( hSenderKey, KP_CERTIFICATE, pbKeyBlob, &dwBlobLen, 0)) { printf("Parameters have been written to the BLOB. \n"); } else { HandleError("Error during CryptGetProvParam."); } //-------------------------------------------------------------------- // Копирование параметров в hResponderKey. if(CryptSetKeyParam( hResponderKey, KP_CERTIFICATE, pbKeyBlob, 0)) { printf("The parameters have been set. \n"); } else { HandleError("Error during CryptSetProvParam."); } CleanUp(); return 0; } void CleanUp(void) { free(pbKeyBlob); // Освобождение дескриптора провайдера. if(hProvResponder) CryptReleaseContext(hProvResponder, 0); if(hProvSender) CryptReleaseContext(hProvSender, 0); // Уничтожение дескрипторов ключей. if(hSenderKey) CryptDestroyKey(hSenderKey); if(hResponderKey) CryptDestroyKey(hResponderKey); if(hSenderEphemKey) CryptDestroyKey(hSenderEphemKey); if(hResponderEphemKey) CryptDestroyKey(hResponderEphemKey); if(hSenderAgreeKey) CryptDestroyKey(hSenderAgreeKey); if(hResponderAgreeKey) CryptDestroyKey(hResponderAgreeKey); } // Конец примера
AIX: 5/6/7 или выше.
FreeBSD: 7/8/9 или выше.
Linux: LSB 3.1 (RHEL 4, SuSE 10) или выше.
Solaris: 10 или выше.
Mac OSX: 10.7/8 или выше.
iOS: 6/7 или выше.
Windows 2000 или выше: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Ядро Windows NT: не поддерживает.