//-------------------------------------------------------------------- // Данный пример демонстрирует экспортирование открытого ключа в файл. // Эта программа используется для экспортирования как открытого ключа // отправителя, так и открытого ключа получателя. // Она необходима для работы таких программ, как зашифрование и // расшифрование содержимого файла. // В PUBLICKEYBLOB не является кроссплатформенной структурой и не защищает // ключи, поэтому рекомендуется использовать сертификаты для обмена открытыми // ключами. Сертификат также записывается в файл, если он есть в контейнере. // Для корректной работы этой программы необходимо создать контейнер // с именем, передаваемым параметром из командной строки. // Контейнер может быть создан при помощи примера CreatingKeyContainer // Замечание: под win32 рекомендуется использовать _s аналоги CRT функций. //-------------------------------------------------------------------- static void WriteBlobToFile(FILE *file, BYTE *pbData, DWORD cbData); static void HandleError(const char *s); static void CleanUp(void); static HCRYPTPROV hProv = 0; // Дескриптор CSP static HCRYPTKEY hKey = 0; // Дескриптор открытого ключа получателя static FILE *Public = NULL; // Файл для хранения открытого ключа static BYTE *pbKeyBlob = NULL; // Указатель на ключевой BLOB static FILE *Cert = NULL; // Файл для хранения сертификата static BYTE *pbCertBlob = NULL; // Указатель BLOB сертификата static char *szFileName = NULL; // Имя файла для экспорта int main(int argc, char *argv[]) { DWORD cbKeyBlob; // Длина ключевого BLOBа DWORD cbCertBlob; // Длина BLOBа сертификата char *szCont = argv[1]; // Короткое имя контейнера if (argc < 2 || strchr(szCont, '\\')) HandleError("Short container name required."); // Получение дескриптора контейнера с именем szCont, // находящегося в рамках провайдера. if(CryptAcquireContextA( &hProv, szCont, NULL, PROV_GOST_2012_256, 0)) { printf("The key container \"%s\" has been acquired.\n", szCont); } else { HandleError("Error during CryptAcquireContext."); } //-------------------------------------------------------------------- // Получение дескриптора открытого ключа. if(CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hKey)) { printf("The public key has been acquired. \n"); } else { HandleError("Error during CryptGetUserKey public key."); } // Запись открытого ключа в ключевой BLOB. // Определение размера BLOBа открытого ключа и распределение памяти. if(CryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, NULL, &cbKeyBlob)) { printf("Size of the BLOB for the public key determined. \n"); } else { HandleError("Error computing BLOB length."); } pbKeyBlob = (BYTE*)malloc(cbKeyBlob); if(!pbKeyBlob) { HandleError("Out of memory. \n"); } // Экспортирование открытого ключа в BLOB открытого ключа. if(CryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &cbKeyBlob)) { printf("Contents have been written to the BLOB. \n"); } else { HandleError("Error during CryptExportKey."); } szFileName = malloc((strlen(szCont) + 5) * sizeof(char)); if(!szFileName) { HandleError("Out of memory. \n"); } strcpy(szFileName, szCont); strcat(szFileName, ".pub"); WriteBlobToFile(Public, pbKeyBlob, cbKeyBlob); // Получение сертификата ключа из контейнера (если он есть) if(CryptGetKeyParam( hKey, KP_CERTIFICATE, NULL, &cbCertBlob, 0)) { pbCertBlob = malloc(cbCertBlob); if(!pbCertBlob) { HandleError("Out of memory. \n"); } if(CryptGetKeyParam( hKey, KP_CERTIFICATE, pbCertBlob, &cbCertBlob, 0)) { printf("Got certificate from container.\n"); } else { HandleError("Error during CryptGetKeyParam."); } strcpy(szFileName, szCont); strcat(szFileName, ".cer"); WriteBlobToFile(Cert, pbCertBlob, cbCertBlob); } else { printf("No certificate in container.\n"); } CleanUp(); printf("The program ran to completion without error. \n"); return 0; } void WriteBlobToFile(FILE *file, BYTE *pbData, DWORD cbData) { // Открытие файла на запись в него BLOB-а //if(!fopen_s(&file, szFileName, "r+b" )) if((file = fopen(szFileName, "wb"))) { printf("The file '%s' was opened\n", szFileName); } else { HandleError("Problem opening the file\n"); } // Запись BLOB-а в файл if(fwrite(pbData, 1, cbData, file)) { printf("The public key was written to the '%s'\n", szFileName); } else { fclose(file); HandleError("The public key can not be written to file.\n"); } fclose(file); } void CleanUp(void) { if(Public) fclose (Public); if(Cert) fclose (Cert); // Освобождение памяти, используемой ключевым BLOBом. free(pbKeyBlob); // Освобождение памяти, используемой BLOBом сертификата. free(pbCertBlob); // Освобождени памяти под имя файла free(szFileName); // Уничтожение дескриптора открытого ключа. if(hKey) CryptDestroyKey(hKey); // Освобождение дескриптора провайдера. if(hProv) CryptReleaseContext(hProv, 0); } // Конец примера
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.