Intial shitty commit
This commit is contained in:
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
build/
|
||||
.vs/
|
||||
out/
|
||||
|
||||
*.enc
|
||||
important_data.txt
|
||||
restored_data.txt
|
||||
private.pem
|
||||
public.pem
|
||||
153
CMakeLists.txt
Normal file
153
CMakeLists.txt
Normal file
@@ -0,0 +1,153 @@
|
||||
cmake_minimum_required(VERSION 3.24) # Requires 3.24+ for URL-based FetchContent binaries
|
||||
project(OpenSSLExample CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
if(WIN32)
|
||||
# Automatically downloads pre-built Windows OpenSSL binaries.
|
||||
# The original placeholder URL "https://github.com" cannot be unpacked by FetchContent.
|
||||
FetchContent_Declare(
|
||||
openssl
|
||||
URL "https://github.com/TaurusTLS-Developers/OpenSSL-Distribution/releases/download/v3.5.6/openssl-3.5.6-Windows-x64.zip"
|
||||
)
|
||||
FetchContent_MakeAvailable(openssl)
|
||||
|
||||
find_path(OPENSSL_INCLUDE_DIR
|
||||
NAMES openssl/evp.h
|
||||
PATHS
|
||||
"${openssl_SOURCE_DIR}/include"
|
||||
"${openssl_SOURCE_DIR}/x64/include"
|
||||
"${openssl_SOURCE_DIR}/win64/include"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6/include"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6-Windows-x64/include"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_library(OPENSSL_CRYPTO_LIB
|
||||
NAMES libcrypto crypto
|
||||
PATHS
|
||||
"${openssl_SOURCE_DIR}/lib"
|
||||
"${openssl_SOURCE_DIR}/x64/lib"
|
||||
"${openssl_SOURCE_DIR}/win64/lib"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6/lib"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6-Windows-x64/lib"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_library(OPENSSL_SSL_LIB
|
||||
NAMES libssl ssl
|
||||
PATHS
|
||||
"${openssl_SOURCE_DIR}/lib"
|
||||
"${openssl_SOURCE_DIR}/x64/lib"
|
||||
"${openssl_SOURCE_DIR}/win64/lib"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6/lib"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6-Windows-x64/lib"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_file(OPENSSL_CRYPTO_DLL
|
||||
NAMES libcrypto-3-x64.dll libcrypto-3.dll
|
||||
PATHS
|
||||
"${openssl_SOURCE_DIR}/bin"
|
||||
"${openssl_SOURCE_DIR}/x64/bin"
|
||||
"${openssl_SOURCE_DIR}/win64/bin"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6/bin"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6-Windows-x64/bin"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
find_file(OPENSSL_SSL_DLL
|
||||
NAMES libssl-3-x64.dll libssl-3.dll
|
||||
PATHS
|
||||
"${openssl_SOURCE_DIR}/bin"
|
||||
"${openssl_SOURCE_DIR}/x64/bin"
|
||||
"${openssl_SOURCE_DIR}/win64/bin"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6/bin"
|
||||
"${openssl_SOURCE_DIR}/openssl-3.5.6-Windows-x64/bin"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if(NOT OPENSSL_INCLUDE_DIR)
|
||||
file(GLOB_RECURSE OPENSSL_EVP_HEADERS "${openssl_SOURCE_DIR}/*/openssl/evp.h")
|
||||
if(OPENSSL_EVP_HEADERS)
|
||||
list(GET OPENSSL_EVP_HEADERS 0 OPENSSL_EVP_HEADER)
|
||||
get_filename_component(OPENSSL_HEADER_DIR "${OPENSSL_EVP_HEADER}" DIRECTORY)
|
||||
get_filename_component(OPENSSL_INCLUDE_DIR "${OPENSSL_HEADER_DIR}" DIRECTORY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_CRYPTO_LIB)
|
||||
file(GLOB_RECURSE OPENSSL_CRYPTO_LIBS
|
||||
"${openssl_SOURCE_DIR}/*libcrypto*.lib"
|
||||
"${openssl_SOURCE_DIR}/*crypto*.lib"
|
||||
"${openssl_SOURCE_DIR}/*libcrypto*.dll.a"
|
||||
)
|
||||
if(OPENSSL_CRYPTO_LIBS)
|
||||
list(GET OPENSSL_CRYPTO_LIBS 0 OPENSSL_CRYPTO_LIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_SSL_LIB)
|
||||
file(GLOB_RECURSE OPENSSL_SSL_LIBS
|
||||
"${openssl_SOURCE_DIR}/*libssl*.lib"
|
||||
"${openssl_SOURCE_DIR}/*ssl*.lib"
|
||||
"${openssl_SOURCE_DIR}/*libssl*.dll.a"
|
||||
)
|
||||
if(OPENSSL_SSL_LIBS)
|
||||
list(GET OPENSSL_SSL_LIBS 0 OPENSSL_SSL_LIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_CRYPTO_DLL)
|
||||
file(GLOB_RECURSE OPENSSL_CRYPTO_DLLS
|
||||
"${openssl_SOURCE_DIR}/*libcrypto-3-x64.dll"
|
||||
"${openssl_SOURCE_DIR}/*libcrypto-3.dll"
|
||||
)
|
||||
if(OPENSSL_CRYPTO_DLLS)
|
||||
list(GET OPENSSL_CRYPTO_DLLS 0 OPENSSL_CRYPTO_DLL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_SSL_DLL)
|
||||
file(GLOB_RECURSE OPENSSL_SSL_DLLS
|
||||
"${openssl_SOURCE_DIR}/*libssl-3-x64.dll"
|
||||
"${openssl_SOURCE_DIR}/*libssl-3.dll"
|
||||
)
|
||||
if(OPENSSL_SSL_DLLS)
|
||||
list(GET OPENSSL_SSL_DLLS 0 OPENSSL_SSL_DLL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_INCLUDE_DIR OR NOT OPENSSL_CRYPTO_LIB OR NOT OPENSSL_SSL_LIB)
|
||||
message(FATAL_ERROR "Downloaded OpenSSL package does not contain the expected include/lib layout.")
|
||||
endif()
|
||||
else()
|
||||
find_package(OpenSSL REQUIRED)
|
||||
set(OPENSSL_INCLUDE_DIR "${OPENSSL_INCLUDE_DIR}")
|
||||
set(OPENSSL_CRYPTO_LIB OpenSSL::Crypto)
|
||||
set(OPENSSL_SSL_LIB OpenSSL::SSL)
|
||||
endif()
|
||||
|
||||
add_executable(crypto_app main.cpp)
|
||||
|
||||
# Link against the downloaded binaries
|
||||
target_include_directories(crypto_app PRIVATE "${OPENSSL_INCLUDE_DIR}")
|
||||
target_link_libraries(crypto_app PRIVATE "${OPENSSL_CRYPTO_LIB}" "${OPENSSL_SSL_LIB}")
|
||||
|
||||
# Copy DLL files to output directory so the executable can run
|
||||
if(WIN32)
|
||||
if(NOT OPENSSL_CRYPTO_DLL OR NOT OPENSSL_SSL_DLL)
|
||||
message(FATAL_ERROR "Downloaded OpenSSL package does not contain the expected DLL files.")
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET crypto_app POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${OPENSSL_CRYPTO_DLL}"
|
||||
"${OPENSSL_SSL_DLL}"
|
||||
$<TARGET_FILE_DIR:crypto_app>
|
||||
)
|
||||
endif()
|
||||
68
README.md
Normal file
68
README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# OpenSSL Hybrid Encryption Test
|
||||
|
||||
Test C++17 project for hybrid file encryption with OpenSSL:
|
||||
|
||||
- RSA key pair generation
|
||||
- AES file encryption
|
||||
- RSA encryption of the temporary AES key
|
||||
- streaming file encryption/decryption
|
||||
|
||||
The application creates a small test file, encrypts it, decrypts it back, and writes the restored result.
|
||||
|
||||
## Requirements
|
||||
|
||||
- CMake 3.24 or newer
|
||||
- C++17 compiler
|
||||
- On Windows: Visual Studio Build Tools or Visual Studio with the Desktop development with C++ workload
|
||||
|
||||
On Windows, `CMakeLists.txt` downloads a pre-built OpenSSL package with `FetchContent` and copies the required DLLs next to the executable.
|
||||
|
||||
## Build
|
||||
|
||||
From the project directory:
|
||||
|
||||
```powershell
|
||||
cmake -S . -B build
|
||||
cmake --build build --config Release
|
||||
```
|
||||
|
||||
If you changed CMake options or headers and want a clean rebuild:
|
||||
|
||||
```powershell
|
||||
cmake --build build --config Release --clean-first
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
With Visual Studio generators, the executable is usually in `build\Release`:
|
||||
|
||||
```powershell
|
||||
cd build\Release
|
||||
.\crypto_app.exe
|
||||
```
|
||||
|
||||
The program generates these files in the current working directory:
|
||||
|
||||
- `private.pem`
|
||||
- `public.pem`
|
||||
- `important_data.txt`
|
||||
- `important_data.enc`
|
||||
- `restored_data.txt`
|
||||
|
||||
Expected console output:
|
||||
|
||||
```text
|
||||
Generating RSA-4096 key pair...
|
||||
Success! Saved 'private.pem' and 'public.pem'.
|
||||
Encrypting file with public key...
|
||||
Decrypting file with private key...
|
||||
Done! Verify 'restored_data.txt' matching original inputs.
|
||||
```
|
||||
|
||||
No output means the files match.
|
||||
|
||||
## Notes
|
||||
|
||||
If CMake reports `No CMAKE_CXX_COMPILER could be found`, install Visual Studio Build Tools and enable the C++ desktop workload.
|
||||
|
||||
If the executable cannot find OpenSSL DLLs, rebuild the project so the post-build copy step can place the DLLs next to `crypto_app.exe`.
|
||||
236
main.cpp
Normal file
236
main.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#define DATA_WRITE(data) reinterpret_cast<const char*>(data)
|
||||
#define DATA_READ(data) reinterpret_cast<char*>(data)
|
||||
|
||||
constexpr size_t BUFFER_SIZE = 4096;
|
||||
// RAII
|
||||
struct PKEYDeleter { void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); } };
|
||||
struct CTXDeleter { void operator()(EVP_PKEY_CTX* p) const { EVP_PKEY_CTX_free(p); } };
|
||||
struct CipherDeleter { void operator()(EVP_CIPHER_CTX* ctx) const { EVP_CIPHER_CTX_free(ctx); } };
|
||||
struct BIODeleter { void operator()(BIO* b) const { BIO_free_all(b); } };
|
||||
|
||||
typedef std::unique_ptr<EVP_PKEY, PKEYDeleter> PRIVATE_KEY;
|
||||
typedef std::unique_ptr<EVP_PKEY_CTX, CTXDeleter> PUBLIC_KEY_CONTEXT;
|
||||
typedef std::unique_ptr<BIO, BIODeleter> KEY_BIO;
|
||||
typedef std::unique_ptr<EVP_CIPHER_CTX, CipherDeleter> CIPTHER_CONTEXT;
|
||||
|
||||
void generate_rsa_keypair(const std::string& private_key_path, const std::string& public_key_path) {
|
||||
// Initialize the context for key generation
|
||||
PUBLIC_KEY_CONTEXT ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr));
|
||||
if (!ctx) {
|
||||
throw std::runtime_error("Failed to create keygen context.");
|
||||
}
|
||||
|
||||
if (EVP_PKEY_keygen_init(ctx.get()) <= 0) {
|
||||
throw std::runtime_error("Failed to initialize keygen context.");
|
||||
}
|
||||
|
||||
// Set the RSA key size
|
||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), 4096) <= 0) {
|
||||
throw std::runtime_error("Failed to set RSA key size.");
|
||||
}
|
||||
|
||||
// Generate key structure
|
||||
EVP_PKEY* raw_pkey = nullptr;
|
||||
if (EVP_PKEY_keygen(ctx.get(), &raw_pkey) <= 0) {
|
||||
throw std::runtime_error("Failed to generate key pair.");
|
||||
}
|
||||
PRIVATE_KEY pkey(raw_pkey);
|
||||
|
||||
// Save the Private Key
|
||||
KEY_BIO priv_bio(BIO_new_file(private_key_path.c_str(), "w"));
|
||||
if (!priv_bio) {
|
||||
throw std::runtime_error("Failed to create private key file.");
|
||||
}
|
||||
// TODO: use private key with password
|
||||
if (PEM_write_bio_PrivateKey(priv_bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr) <= 0) {
|
||||
throw std::runtime_error("Failed to write private key to file.");
|
||||
}
|
||||
|
||||
// Save the Public Key
|
||||
KEY_BIO pub_bio(BIO_new_file(public_key_path.c_str(), "w"));
|
||||
if (!pub_bio)
|
||||
throw std::runtime_error("Failed to create public key file.");
|
||||
|
||||
if (PEM_write_bio_PUBKEY(pub_bio.get(), pkey.get()) <= 0)
|
||||
throw std::runtime_error("Failed to write public key to file.");
|
||||
}
|
||||
|
||||
// Load Public Key from file
|
||||
PRIVATE_KEY load_public_key(const std::string& path) {
|
||||
KEY_BIO file(BIO_new_file(path.c_str(), "r"));
|
||||
if (!file)
|
||||
throw std::runtime_error("Cannot open public key file.");
|
||||
|
||||
EVP_PKEY* pkey = PEM_read_bio_PUBKEY(file.get(), nullptr, nullptr, nullptr);
|
||||
if (!pkey)
|
||||
throw std::runtime_error("Failed to read public key.");
|
||||
return PRIVATE_KEY(pkey);
|
||||
}
|
||||
|
||||
// Load Private Key from file
|
||||
PRIVATE_KEY load_private_key(const std::string& path) {
|
||||
KEY_BIO file(BIO_new_file(path.c_str(), "r"));
|
||||
|
||||
if (!file)
|
||||
throw std::runtime_error("Cannot open private key file.");
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(file.get(), nullptr, nullptr, nullptr);
|
||||
if (!pkey)
|
||||
throw std::runtime_error("Failed to read private key.");
|
||||
|
||||
return PRIVATE_KEY(pkey);
|
||||
}
|
||||
|
||||
// ENCRYPTION
|
||||
void hybrid_encrypt(const std::string& input_path, const std::string& output_path, const std::string& pub_key_path) {
|
||||
auto pub_key = load_public_key(pub_key_path);
|
||||
|
||||
// Generate ephemeral AES key and IV
|
||||
unsigned char aes_key[32];
|
||||
unsigned char iv[16];
|
||||
if (RAND_bytes(aes_key, sizeof(aes_key)) != 1 || RAND_bytes(iv, sizeof(iv)) != 1) {
|
||||
throw std::runtime_error("Failed to generate random AES key/IV.");
|
||||
}
|
||||
|
||||
// Encrypt the AES key using the RSA Public Key
|
||||
PUBLIC_KEY_CONTEXT rsa_ctx(EVP_PKEY_CTX_new(pub_key.get(), nullptr));
|
||||
if (!rsa_ctx || EVP_PKEY_encrypt_init(rsa_ctx.get()) <= 0)
|
||||
throw std::runtime_error("RSA init failed.");
|
||||
|
||||
size_t encrypted_key_len = 0;
|
||||
if (EVP_PKEY_encrypt(rsa_ctx.get(), nullptr, &encrypted_key_len, aes_key, sizeof(aes_key)) <= 0) {
|
||||
throw std::runtime_error("RSA encrypted key size calculation failed.");
|
||||
}
|
||||
std::vector<unsigned char> encrypted_key(encrypted_key_len);
|
||||
if (EVP_PKEY_encrypt(rsa_ctx.get(), encrypted_key.data(), &encrypted_key_len, aes_key, sizeof(aes_key)) <= 0)
|
||||
throw std::runtime_error("RSA encryption failed.");
|
||||
|
||||
// Open file streams
|
||||
std::ifstream in_file(input_path, std::ios::binary);
|
||||
std::ofstream out_file(output_path, std::ios::binary);
|
||||
if (!in_file || !out_file) throw std::runtime_error("File stream error.");
|
||||
|
||||
// Write metadata header
|
||||
uint32_t key_len_header = static_cast<uint32_t>(encrypted_key_len);
|
||||
out_file.write(DATA_WRITE(&key_len_header), sizeof(key_len_header));
|
||||
out_file.write(DATA_WRITE(encrypted_key.data()), encrypted_key_len);
|
||||
out_file.write(DATA_WRITE(iv), sizeof(iv));
|
||||
|
||||
// Stream encrypt the actual file data via AES
|
||||
CIPTHER_CONTEXT aes_ctx(EVP_CIPHER_CTX_new());
|
||||
if (!aes_ctx || EVP_EncryptInit_ex(aes_ctx.get(), EVP_aes_256_cbc(), nullptr, aes_key, iv) != 1) {
|
||||
throw std::runtime_error("AES init failed.");
|
||||
}
|
||||
|
||||
std::vector<char> in_buf(BUFFER_SIZE);
|
||||
std::vector<unsigned char> out_buf(BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH);
|
||||
int out_len = 0;
|
||||
|
||||
while (in_file.read(in_buf.data(), BUFFER_SIZE) || in_file.gcount() > 0) {
|
||||
if (EVP_EncryptUpdate(aes_ctx.get(), out_buf.data(), &out_len,
|
||||
reinterpret_cast<const unsigned char*>(in_buf.data()), in_file.gcount()) != 1) {
|
||||
throw std::runtime_error("AES update failed.");
|
||||
}
|
||||
out_file.write(DATA_WRITE(out_buf.data()), out_len);
|
||||
}
|
||||
|
||||
if (EVP_EncryptFinal_ex(aes_ctx.get(), out_buf.data(), &out_len) != 1)
|
||||
throw std::runtime_error("AES final failed.");
|
||||
out_file.write(DATA_WRITE(out_buf.data()), out_len);
|
||||
}
|
||||
|
||||
// DECRYPTION
|
||||
void hybrid_decrypt(const std::string& input_path, const std::string& output_path, const std::string& priv_key_path) {
|
||||
auto priv_key = load_private_key(priv_key_path);
|
||||
|
||||
std::ifstream input_file(input_path, std::ios::binary);
|
||||
std::ofstream output_file(output_path, std::ios::binary);
|
||||
if (!input_file || !output_file) throw std::runtime_error("File stream error.");
|
||||
|
||||
// Read metadata header
|
||||
uint32_t encrypted_key_len = 0;
|
||||
input_file.read(DATA_READ(&encrypted_key_len), sizeof(encrypted_key_len));
|
||||
|
||||
std::vector<unsigned char> encrypted_key(encrypted_key_len);
|
||||
input_file.read(DATA_READ(encrypted_key.data()), encrypted_key_len);
|
||||
|
||||
unsigned char iv[16]{};
|
||||
input_file.read(DATA_READ(iv), sizeof(iv));
|
||||
|
||||
// Decrypt the secret AES key using the RSA Private Key
|
||||
PUBLIC_KEY_CONTEXT rsa_ctx(EVP_PKEY_CTX_new(priv_key.get(), nullptr));
|
||||
if (!rsa_ctx || EVP_PKEY_decrypt_init(rsa_ctx.get()) <= 0) throw std::runtime_error("RSA decrypt init failed.");
|
||||
|
||||
size_t aes_key_len = 0;
|
||||
if (EVP_PKEY_decrypt(rsa_ctx.get(), nullptr, &aes_key_len, encrypted_key.data(), encrypted_key_len) <= 0)
|
||||
throw std::runtime_error("RSA decrypted key size calculation failed.");
|
||||
|
||||
std::vector<unsigned char> aes_key(aes_key_len);
|
||||
if (EVP_PKEY_decrypt(rsa_ctx.get(), aes_key.data(), &aes_key_len, encrypted_key.data(), encrypted_key_len) <= 0) {
|
||||
throw std::runtime_error("RSA decryption failed. Key might be wrong or corrupted.");
|
||||
}
|
||||
if (aes_key_len != 32)
|
||||
throw std::runtime_error("RSA decryption produced an unexpected AES key size.");
|
||||
|
||||
aes_key.resize(aes_key_len);
|
||||
|
||||
// Stream decrypt the file data using the recovered AES key
|
||||
CIPTHER_CONTEXT aes_ctx(EVP_CIPHER_CTX_new());
|
||||
if (!aes_ctx || EVP_DecryptInit_ex(aes_ctx.get(), EVP_aes_256_cbc(), nullptr, aes_key.data(), iv) != 1) {
|
||||
throw std::runtime_error("AES decrypt init failed.");
|
||||
}
|
||||
|
||||
std::vector<char> input_buf(BUFFER_SIZE);
|
||||
std::vector<unsigned char> output_buf(BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH);
|
||||
int out_len = 0;
|
||||
|
||||
while (input_file.read(input_buf.data(), BUFFER_SIZE) || input_file.gcount() > 0) {
|
||||
if (EVP_DecryptUpdate(aes_ctx.get(), output_buf.data(), &out_len,
|
||||
reinterpret_cast<const unsigned char*>(input_buf.data()), input_file.gcount()) != 1) {
|
||||
throw std::runtime_error("AES decrypt update failed.");
|
||||
}
|
||||
output_file.write(DATA_READ(output_buf.data()), out_len);
|
||||
}
|
||||
|
||||
if (EVP_DecryptFinal_ex(aes_ctx.get(), output_buf.data(), &out_len) != 1) {
|
||||
throw std::runtime_error("Decryption integrity check failed.");
|
||||
}
|
||||
output_file.write(DATA_READ(output_buf.data()), out_len);
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
// Setup a test file
|
||||
std::ofstream f("important_data.txt");
|
||||
f << "Top secret hybrid structural data streams.";
|
||||
|
||||
std::cout << "Generating RSA-4096 key pair...\n";
|
||||
generate_rsa_keypair("private.pem", "public.pem");
|
||||
std::cout << "Success! Saved 'private.pem' and 'public.pem'.\n";
|
||||
|
||||
std::cout << "Encrypting file with public key...\n";
|
||||
hybrid_encrypt("important_data.txt", "important_data.enc", "public.pem");
|
||||
|
||||
std::cout << "Decrypting file with private key...\n";
|
||||
hybrid_decrypt("important_data.enc", "restored_data.txt", "private.pem");
|
||||
|
||||
std::cout << "Done! Verify 'restored_data.txt' matching original inputs.\n";
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Pipeline failure: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user