#include #include #include #include #include #include #include #include namespace CryptoLib { std::pair, std::unique_ptr> generate_keys(int key_size = 2048); std::pair, std::unique_ptr> generate_keys(int key_size) { Botan::AutoSeeded_RNG rng; std::unique_ptr private_key(new Botan::RSA_PrivateKey(rng, key_size)); std::unique_ptr public_key(new Botan::RSA_PublicKey(*private_key)); return std::make_pair(std::move(private_key), std::move(public_key)); } std::vector encrypt(const Botan::Public_Key& public_key, const std::string& data) { std::vector data_vector(data.begin(), data.end()); Botan::AutoSeeded_RNG rng; Botan::PK_Encryptor_EME encryptor(public_key, rng, "OAEP(SHA-256)"); return encryptor.encrypt(data_vector, rng); } std::string decrypt(const Botan::Private_Key& private_key, const std::vector& encrypted_data) { std::vector encrypted_vector(encrypted_data.begin(), encrypted_data.end()); Botan::AutoSeeded_RNG rng; Botan::PK_Decryptor_EME decryptor(private_key, rng, "OAEP(SHA-256)"); auto result = decryptor.decrypt(encrypted_vector); return std::string(result.begin(), result.end()); } std::string public_key_to_string(const Botan::Public_Key& public_key) { return Botan::X509::PEM_encode(public_key); } std::unique_ptr public_key_from_string(const std::string& key_string) { Botan::DataSource_Memory ds(key_string); return std::unique_ptr(Botan::X509::load_key(ds)); } std::string private_key_to_string(const Botan::Private_Key& private_key) { return Botan::PKCS8::PEM_encode(private_key); } std::unique_ptr private_key_from_string(const std::string& key_string) { Botan::DataSource_Memory ds(key_string); return std::unique_ptr(Botan::PKCS8::load_key(ds)); } void save_private_key(const Botan::Private_Key& private_key, const std::string& filename) { std::ofstream file(filename); if (file.is_open()) { file << Botan::PKCS8::PEM_encode(private_key); file.close(); } else { throw std::runtime_error("Cannot open file for writing: " + filename); } } void save_public_key(const Botan::Public_Key& public_key, const std::string& filename) { std::ofstream file(filename); if (file.is_open()) { file << Botan::X509::PEM_encode(public_key); file.close(); } else { throw std::runtime_error("Cannot open file for writing: " + filename); } } std::unique_ptr load_private_key(const std::string& filename) { std::ifstream file(filename); if (file.is_open()) { std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); Botan::DataSource_Memory ds(content); return std::unique_ptr(Botan::PKCS8::load_key(ds)); } else { throw std::runtime_error("Cannot open file for reading: " + filename); } } std::unique_ptr load_public_key(const std::string& filename) { std::ifstream file(filename); if (file.is_open()) { std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); Botan::DataSource_Memory ds(content); return std::unique_ptr(Botan::X509::load_key(ds)); } else { throw std::runtime_error("Cannot open file for reading: " + filename); } } std::string bytes_to_base64(const std::vector& data) { static const char* const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string result; size_t i = 0; while (i < data.size()) { uint32_t octet_a = i < data.size() ? data[i++] : 0; uint32_t octet_b = i < data.size() ? data[i++] : 0; uint32_t octet_c = i < data.size() ? data[i++] : 0; uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c; result += chars[(triple >> 18) & 63]; result += chars[(triple >> 12) & 63]; result += chars[(triple >> 6) & 63]; result += chars[triple & 63]; } // Add padding switch (data.size() % 3) { case 1: result[result.size() - 2] = '='; result[result.size() - 1] = '='; break; case 2: result[result.size() - 1] = '='; break; } return result; } std::vector base64_to_bytes(const std::string& input) { static const std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::vector result; int val = 0, valb = -8; for (unsigned char c : input) { if (c == '=') break; if (chars.find(c) == std::string::npos) continue; val = (val << 6) + chars.find(c); valb += 6; if (valb >= 0) { result.push_back((val >> valb) & 0xFF); valb -= 8; } } return result; } };