Как передать сессионный ключ для дешифровки в cryptoapi

Необходимо шифровать строки в файле при помощи CryptoAPI, а потом расшифровывать его и читать данные.

Начальный ключ генерирую так:

    HCRYPTPROV hProv;
    HCRYPTKEY hSessionKey;

    if(!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){
        cout << "Error, getting encryption context" << endl;
        return 1;
    }

    cout << "Cryptographic provider successfully initialized!" << endl;

    if(!CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hSessionKey)){
        cout << "Error, generating session key for encryption!" << endl;
        return 1;
    }
    cout << "Session key successfully generated!" << endl;

После этого передаю в функцию сохранения файла, которая для каждой строки вызывает функцию шифрования:

Crypto* CWEncrypt(const char* toEncode, HCRYPTKEY hSessionKey) {
    char *tempString;
    tempString = new char[strlen(toEncode)];
    strcpy_s(tempString, strlen(tempString), toEncode);
    DWORD count = strlen(tempString);
    if(!CryptEncrypt(hSessionKey, NULL, true, NULL, reinterpret_cast<BYTE*>(tempString), &count, count)){
        cout << "Error, encrypting provided data" << endl;
        return nullptr;
    }
    auto response = new Crypto(tempString, hSessionKey); //Crypto is a struct with fields with types string and HCRYPTKEY
    return response;
}

После сохранения hSessionKey выводится пользователю на экран. Потом при попытке загрузиться из файла у человека спрашивают hSessionKey, который он вводит через cin. Этот же ключ отправляется в функцию дешифрования:



char* CWDecrypt(const char* toDecode, HCRYPTKEY hSessionKey) {
    char *tempString;
    tempString = new char[strlen(toDecode)];
    strcpy_s(tempString, strlen(tempString), toDecode);
    DWORD count = strlen(tempString);
    if(!CryptDecrypt(hSessionKey, NULL, true, NULL, reinterpret_cast<BYTE*>(tempString), &count)){
        cout << "Error, decrypting provided data" << endl;
        return nullptr;
    }

    return tempString;
}

И вот тут уже возникает ошибка - отрабатывает if и выдаёт Error, decrypting provided data.

При этом сами функции рабочие, и такой код в мэйне работает:

    string ss = "String to encrypt and decrypt";
    Crypto cr = *CWEncrypt(ss.c_str());
    ss = cr.getValue();
    cout << ss << endl;
    cout << CWDecrypt(ss.c_str(), cr.getSessionKey()) << endl;

Судя по всему, просто передать ключ не достаточно, и его нужно заново сгенерировать по какому-то другому ключу. hPov для этого не подходит, так как hSessionKey генерируется другой и расшифровать данные не получается. Среди функций нашёл CryptExportKey, но он в качестве параметра принимает ещё какой-то ключ, который я без понятия где взять.

И очень большая просьба знатокам, даже если вопрос кажется глупым и простым, не молча минусить его, а хотя бы перед выставлением минуса ответить, как это реализовать, раз уж это так просто, а я дурак не догадался. Спасибо.

UPD: Попытка сохранить hSessionKey в файл тоже успехом не увенчалась.

UPD 2: Нашёл хоть какую-то информацию о CryptExportKey. В некоторых источниках написано, что второй ключ, который туда нужно передавать - это открытый ключ, который потом при дешифровании нужно будет ввести, но если он не нужен, то можно ввести NULL. При этом изначально нужно получать длину итогового экспортируемого ключа, и для этого нужно запустить CryptExportKey, и в качестве адреса, куда ключ записывать, передавать NULL:


DWORD dwPublicKeyLen;
if (!CryptExportKey( hSessionKey, hUserKey,
                         SIMPLEBLOB, NULL, NULL /* Also I tried to use nullptr here, and it didn't help */, &dwPublicKeyLen)) {
        cout << "Error, exporting key for encryption!" << endl;
        return 1;
}
BYTE* hPublicKey = static_cast<BYTE*>(malloc(dwPublicKeyLen));
if (!CryptExportKey( hSessionKey, NULL,
                         SIMPLEBLOB, NULL, hPublicKey, &dwPublicKeyLen)){
        cout << "Error, exporting key for encryption!" << endl;
        return 1;
}

И на этом моменте отрабатывает первый if и выдаёт ошибку. Подумал, что, может, там ошиблись, и без открытого ключа экспортировать сессионный ключ нельзя, так что стал пробовать перед этим генерировать его, опять же по примерам, которые смог найти:

HCRYPTKEY hUserKey;
if (!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hUserKey)) {
        cout << "Error, generating user key!" << endl;
        return 1;
}

Здесь ошибка (отработка if) начинает возникать уже при генерации этого ключа. Я в ещё большем замешательстве...


Ответы (0 шт):