C++. Как правильно конвертировать std::string (с массивом байт) в const std::char*

Я использую библиотеку CryptoPP для AES и RSA шифрования. И у меня возникает проблема при преобразовании std::string в const std::char*. На сколько я понимаю (по скриншотам ниже), проблема заключается в том, что функция .c_str() обрезает строку в месте где встречается \0 или подобный символ.

Это функция шифрования:

string RSACryptography::Encrypt(string text) {
    string cipher_text;
    CryptoPP::StringSource(text, true, new CryptoPP::PK_EncryptorFilter(this->rng, this->publicKey, new CryptoPP::StringSink(cipher_text)));
    return cipher_text;
}

Здесь я вызываю эту функцию:

int main() {
    RSACryptography* CryptoRSA = new RSACryptography();
    string cipher_text = CryptoRSA->Encrypt("hellO");

    cout << "cipher text (string):\n" << cipher_text << "\n\n\n\n";
    
    cout << "cipher text (string.c_str()):\n" << cipher_text.c_str() << endl;
}

CryptoPP шифрует текст и пишет его в строку. При обычном выводе строки, и дальнейшей передаче в функцию дешифрования всё работает отлично. Однако при попытке перевести std::string в const std::char* (чем по сути string и является) возникает вот такая проблема:

скриншот консоли вывода

НО! В то же время, вероятность того, что функция .c_str() обрежет строку, около 80%. То есть бывают случаи когда правильно возвращается вся строка (в последующем для функции const_cast). Прошу, подскажите варианты того, как правильно конвертировать такую строку в const std::char*.

P.S. Конвертировать std::string в const std::char* мне нужно для того, что бы я мог передать такую строку в Python. А для этого существует только 2 варианта типов: const std::char* или const std::wchar_t*

P.S.S. Когда я дешифрую полученную строку, всё прекрасно работает. 10 раз запустил, 10 раз сработало. Тогда я конвертирую шифрованную строку в const std::char* и передаю её в функцию дешифрования. 10 раз запустил, 3 раза сработало(7 раз вылетело в ошибку) :(

int main() {
    RSACryptography* RSACrypt = new RSACryptography();
    string cipher_text = RSACrypt->Encrypt("hellO");

    cout << "cipher text (string):\n" << cipher_text << "\n\n\n\n";
    
    const char* cipher_text_char = const_cast<char*>(cipher_text.c_str());

    cout << RSACrypt->Decipher(cipher_text_char);
}


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

Автор решения: Harry

Проблема, как я понимаю, в том, что

string RSACryptography::Decipher(string text) 

Теперь смотрите - если вы передаете string - она идет со всеми нулевыми символами, все OK.

Но когда вы передаете аргументом char*, то сначала вызывается конструктор строки string для ее получения из char* - а этот конструктор, видя нулевой символ, считает это окончанием строки!

Вот тут обрезание и происходит...

См. тут описание пятого конструктора - он полагает, что ему передается строка с завершающим нулевым символом.

Разжевываю.

Пусть после шифрования строка string cifer состоит из каких-то байт, типа

05 3A 18 00 24 38 63

Если мы передает ее как строку для дешифровки - передаются все 7 байт. Но если мы передаем указатель на этот массив - то, поскольку функция принимает string, а не char*, сначала выполняется создание строки из этой последовательности символов. Конструктор string создан так, что если он получает указатель - то считает, что это указатель на строку с завершающим нулевым символом. Он создает новую строк string содержимое которой теперь

05 3A 18

Все! Потому что дальше - нулевой символ, строка считается завершенной - ну вот так написан конструктор!

Вот и несоответствие размеру, и обрезка по нулевому символу. Так понятно?

→ Ссылка