//-------------------------------------------------------------------- // В данном примере осуществляется экспортирование сессионного ключа // при помощи сертификатов получателя и отправителя. // Для корректной работы этой программы необходимо создать два // сертификата и добавить их в хранилище сертификатов MY: получателя // (с именем, содержащим "Responder") и отправителя (c именем, содержащим // "Sender"). //-------------------------------------------------------------------- static void HandleError(const char *s); static void CleanUp(BOOL); static HCERTSTORE hStoreHandle = 0; // Дескриптор хранилища сертификатов static PCCERT_CONTEXT pCertSender = NULL; // Контекст сертификата отправителя static PCCERT_CONTEXT pCertResponder = NULL; // Контекст сертификата получателя static HCRYPTPROV hProvResponder = 0; // Дескриптор CSP получателя static HCRYPTPROV hProvSender = 0; // Дескриптор CSP отправителя static HCRYPTKEY hSenderKey = 0; // Дескриптор открытого ключа отправителя static HCRYPTKEY hResponderKey = 0; // Дескриптор открытого ключа получателя static HCRYPTKEY hSessionKey = 0; // Дескриптор сессионного ключа static HCRYPTKEY hAgreeKey = 0; // Дескриптор ключа согласования static BYTE *pbKeyBlobSimple = NULL; // Указатель на сессионный ключевой BLOB static BYTE *pbKeyBlobSender = NULL; // Указатель на ключевой BLOB отправителя static BYTE *pbKeyBlobResponder = NULL; // Указатель на ключевой BLOB получателя int main(void) { DWORD dwBlobLenSimple; // Длина сессионного ключевого BLOBа DWORD dwBlobLenSender; // Длина ключевого BLOBа отправителя DWORD dwBlobLenResponder; // Длина ключевого BLOBа получателя DWORD dwKeySpecSender; DWORD dwKeySpecResponder; // На стороне отправителя: // Открытие системного хранилища сертификатов. hStoreHandle = CertOpenSystemStore(0, _TEXT("MY")); if(hStoreHandle) { printf("The MY store is open. \n"); } else { HandleError( "Error getting store handle."); } //-------------------------------------------------------------------- // Получение контекста сертифика, в названии которого содержится "Sender", // находящегося в хранилище сертификатов "MY". pCertSender = CertFindCertificateInStore( hStoreHandle, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_W, L"Sender", NULL); if(pCertSender) { printf("The \" Sender \" certificate is found. \n"); } else { HandleError( "Error finding certificate."); } //-------------------------------------------------------------------- // Получение дескриптора CSP, включая доступ к связанному с ним ключевому // контейнеру для контекста сертификата pCertSender. if(CryptAcquireCertificatePrivateKey( pCertSender, 0, NULL, &hProvSender, &dwKeySpecSender, NULL)) { printf("The CSP handle has been acquired. \n"); } else { HandleError("Error during CryptAcquireCertificatePrivateKey."); } //-------------------------------------------------------------------- // Поиск сертифика, в названии которого содержится "Responder", // находящегося в хранилище сертификатов "MY". pCertResponder = CertFindCertificateInStore( hStoreHandle, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_W, L"Responder", NULL); if(pCertResponder) { printf("The \" Responder \" certificate is found. \n"); } else { HandleError( "Error finding certificate."); } //-------------------------------------------------------------------- // Получение дескриптора открытого ключа получателя. if(CryptImportPublicKeyInfoEx( hProvSender, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertResponder->pCertInfo->SubjectPublicKeyInfo), 0, 0, NULL, &hResponderKey)) { printf("The responder public key has been acquired. \n"); } else { HandleError("Error during CryptImportPublicKeyInfoEx public key."); } //-------------------------------------------------------------------- // Определение размера BLOBа открытого ключа и распределение памяти. if(CryptExportKey( hResponderKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLenResponder)) { printf("Size of the BLOB for the responder public key determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlobResponder = (BYTE*)malloc(dwBlobLenResponder); if(pbKeyBlobResponder) { printf("Memory has been allocated for the BLOB. \n"); } else { HandleError("Out of memory. \n"); } //-------------------------------------------------------------------- // Экспортирование открытого ключа получателя в BLOB открытого ключа. if(CryptExportKey( hResponderKey, 0, PUBLICKEYBLOB, 0, pbKeyBlobResponder, &dwBlobLenResponder)) { printf("Contents have been written to the BLOB. \n"); } else { HandleError("Error during CryptExportKey."); } //-------------------------------------------------------------------- // Получение дескриптора закрытого ключа отправителя. if(CryptGetUserKey( hProvSender, dwKeySpecSender, &hSenderKey)) { printf("The sender private key has been acquired. \n"); } else { HandleError("Error during CryptGetUserKey private key."); } //-------------------------------------------------------------------- // Получение ключа согласования импортом открытого ключа получателя из BLOBа // на закрытом ключе отправителя. if(CryptImportKey( hProvSender, pbKeyBlobResponder, dwBlobLenResponder, hSenderKey, 0, &hAgreeKey)) { printf("The responder public key has been imported. \n"); } else { HandleError("Error during CryptImportKey public key."); } //-------------------------------------------------------------------- // Генерация сессионного ключа. if(CryptGenKey( hProvSender, CALG_G28147, CRYPT_EXPORTABLE, &hSessionKey)) { printf("Original session key is created. \n"); } else { HandleError("ERROR -- CryptGenKey."); } //-------------------------------------------------------------------- // pbKeyBlobSimple - зашифрованный сессионный ключ, передаем его получателю // //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Определение размера BLOBа сессионного ключа и распределение памяти. if(CryptExportKey( hSessionKey, hAgreeKey, SIMPLEBLOB, 0, NULL, &dwBlobLenSimple)) { printf("Size of the BLOB for the sender session key determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlobSimple = (BYTE*)malloc(dwBlobLenSimple); if(pbKeyBlobSimple) { printf("Memory has been allocated for the BLOB. \n"); } else { HandleError("Out of memory. \n"); } //-------------------------------------------------------------------- // Шифрование сессионного ключа на ключе Agree. if(CryptExportKey( hSessionKey, hAgreeKey, SIMPLEBLOB, 0, pbKeyBlobSimple, &dwBlobLenSimple)) { printf("Contents have been written to the BLOB. \n"); } else { HandleError("Error during CryptExportKey."); } //-------------------------------------------------------------------- // Закрытие системного хранилища сертификатов. if(CertCloseStore( hStoreHandle, 0)) { printf("The MY store is closed. \n"); hStoreHandle=0; } else { HandleError( "Error closing store handle."); } CleanUp(FALSE); //-------------------------------------------------------------------- // На стороне получателя: получили зашифрованный сессионный ключ // pbKeyBlobSimple. //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Открытие системного хранилища сертификатов. hStoreHandle = CertOpenSystemStore(0, _TEXT("MY")); if(hStoreHandle) { printf("The MY store is open. \n"); } else { HandleError( "Error getting store handle."); } //-------------------------------------------------------------------- // Получение контекста сертифика, в названии которого содержится "Responder", // находящегося в хранилище сертификатов "MY". pCertResponder = CertFindCertificateInStore( hStoreHandle, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_W, L"Responder", NULL); if(pCertResponder) { printf("The \" Responder \" certificate is found. \n"); } else { HandleError( "Error finding certificate."); } //-------------------------------------------------------------------- // Получение дескриптора CSP, включая доступ к связанному с ним ключевому // контейнеру для контекста сертификата pCertResponder. if(CryptAcquireCertificatePrivateKey( pCertResponder, 0, NULL, &hProvResponder, &dwKeySpecResponder, NULL)) { printf("The CSP handle has been acquired. \n"); } else { HandleError("Error during CryptAcquireCertificatePrivateKey."); } //-------------------------------------------------------------------- // Поиск сертифика, в названии которого содержится "Sender", // находящегося в хранилище сертификатов "MY". pCertSender = CertFindCertificateInStore( hStoreHandle, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_W, L"Sender", NULL); if(pCertSender) { printf("The \" Sender \" certificate is found. \n"); } else { HandleError( "Error finding certificate."); } //-------------------------------------------------------------------- // Получение дескриптора открытого ключа отправителя. if(CryptImportPublicKeyInfoEx( hProvResponder, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertSender->pCertInfo->SubjectPublicKeyInfo), 0, 0, NULL, &hSenderKey)) { printf("The sender public key has been acquired. \n"); } else { HandleError("Error during CryptImportPublicKeyInfoEx public key."); } //-------------------------------------------------------------------- // Определение размера BLOBа открытого ключа и распределение памяти. if(CryptExportKey( hSenderKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLenSender)) { printf("Size of the BLOB for the sender public key determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlobSender = (BYTE*)malloc(dwBlobLenSender); if(pbKeyBlobSender) { printf("Memory has been allocated for the BLOB. \n"); } else { HandleError("Out of memory. \n"); } //-------------------------------------------------------------------- // Экспортирование открытого ключа отправителя в BLOB открытого ключа. if(CryptExportKey( hSenderKey, 0, PUBLICKEYBLOB, 0, pbKeyBlobSender, &dwBlobLenSender)) { printf("Contents have been written to the BLOB. \n"); } else { HandleError("Error during CryptExportKey."); } //-------------------------------------------------------------------- // Получение дескриптора закрытого ключа получателя. if(CryptGetUserKey( hProvResponder, dwKeySpecResponder, &hResponderKey)) { printf("The responder private key has been acquired. \n"); } else { HandleError("Error during CryptGetUserKey private key."); } //-------------------------------------------------------------------- // Получение ключа согласования импортом открытого ключа отправителя из BLOBа // на закрытом ключе получателя. if(CryptImportKey( hProvResponder, pbKeyBlobSender, dwBlobLenSender, hResponderKey, 0, &hAgreeKey)) { printf("The sender public key has been imported. \n"); } else { HandleError("Error during CryptImportKey public key."); } // Получение сессионного ключа импортом зашифрованного сессионного ключа // на ключе Agree. if(CryptImportKey( hProvResponder, pbKeyBlobSimple, dwBlobLenSimple, hAgreeKey, 0, &hSessionKey)) { printf("The session key has been imported. \n"); } else { HandleError("Error during CryptImportKey session key."); } CleanUp(TRUE); printf("The program ran to completion without error. \n"); return 0; } void CleanUp(BOOL all) { if(pbKeyBlobResponder) { free(pbKeyBlobResponder); pbKeyBlobResponder=NULL; } if(pbKeyBlobSimple && all) { free(pbKeyBlobSimple); pbKeyBlobSimple=NULL; } if(pbKeyBlobSender) { free(pbKeyBlobSender); pbKeyBlobSender=NULL; } if(hStoreHandle) { CertCloseStore(hStoreHandle, 0); hStoreHandle=0; } // Освобождение дескриптора провайдера. if(hProvSender) { CryptReleaseContext(hProvSender, 0); hProvSender=0; } // Уничтожение дескриптора закрытого ключа получателя. if(hResponderKey) { CryptDestroyKey(hResponderKey); hResponderKey=0; } // Уничтожение дескриптора открытого ключа отправителя. if(hSenderKey) { CryptDestroyKey(hSenderKey); hSenderKey=0; } // Уничтожение сессионного ключа. if(hSessionKey) { CryptDestroyKey(hSessionKey); hSessionKey=0; } // Уничтожение ключа согласования. if(hAgreeKey) { CryptDestroyKey(hAgreeKey); hAgreeKey=0; } // Освобождение дескриптора провайдера. if(hProvResponder) { CryptReleaseContext(hProvResponder, 0); hProvResponder=0; } // Освобождение контекста сертификата. if(pCertSender) { CertFreeCertificateContext(pCertSender); pCertSender=NULL; } if(pCertResponder) { CertFreeCertificateContext(pCertResponder); pCertResponder=NULL; } } // Конец примера
AIX: 6/7.
FreeBSD: 11/12, pfSense 2.x.
Linux: LSB 4.x (RHEL 5/6/7/8, SuSE 11SP4/12/15, Oracle Linux 5/6/7/8, CentOS 6/7/8, Ubuntu 14.04/16.04/18.04/19.10, Linux Mint 18/19, Fedora 28/29/30/31, Debian 8/9/10 и др.).
Solaris: 10/11.
Mac OS X: 10.9/10.10/10.11/10.12/10.13/10.14/10.15.
iOS: 8/9/10/11/12/13.
Sailfish: 2/3.
Windows: 7/8/8.1/10, Server 2008/2008R2/2012/2012R2/2016/2019.