From b1acb0ba815f955d9971e45a88af6c3dbf50c597 Mon Sep 17 00:00:00 2001 From: elpatron Date: Thu, 28 Aug 2025 09:41:19 +0200 Subject: [PATCH] Implement actual cryptographic functions using Crypto++ library --- CMakeLists.txt | 39 +++++++++++ build.bat | 7 +- src/crypto.cpp | 182 +++++++++++++++++++++++++++++++++++++------------ 3 files changed, 184 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd4c3e1..54fcae2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,41 @@ else() endif() endif() +# Handle Crypto++ dependency +# First try to find it as a package +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(CRYPTOPP QUIET libcrypto++ cryptopp) +endif() + +if(CRYPTOPP_FOUND) + # Use the found package + message(STATUS "Found Crypto++ package") + set(CRYPTOPP_INCLUDE_DIRS ${CRYPTOPP_INCLUDE_DIRS}) + set(CRYPTOPP_LIBRARIES ${CRYPTOPP_LIBRARIES}) +else() + # Download it as a submodule or include it directly + message(STATUS "Crypto++ not found as package, will use submodule") + + # Check if we have it in external/cryptopp + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/external/cryptopp/cryptlib.h") + set(CRYPTOPP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/cryptopp") + # For local build, we assume the library is built separately + set(CRYPTOPP_LIBRARIES cryptopp) + else() + # Try to download it + include(FetchContent) + FetchContent_Declare( + cryptopp + GIT_REPOSITORY https://github.com/weidai11/cryptopp.git + GIT_TAG CRYPTOPP_8_8_0 + ) + FetchContent_MakeAvailable(cryptopp) + set(CRYPTOPP_INCLUDE_DIRS ${cryptopp_SOURCE_DIR}) + set(CRYPTOPP_LIBRARIES cryptopp) + endif() +endif() + # Add library sources set(SOURCES src/privatebinapi.cpp @@ -77,6 +112,10 @@ else() target_include_directories(privatebinapi PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS}) endif() +# Include Crypto++ +target_include_directories(privatebinapi PRIVATE ${CRYPTOPP_INCLUDE_DIRS}) +target_link_libraries(privatebinapi ${CRYPTOPP_LIBRARIES}) + # Link dependencies target_link_libraries(privatebinapi ${PLATFORM_LIBS}) diff --git a/build.bat b/build.bat index 93e2078..f4b85ea 100644 --- a/build.bat +++ b/build.bat @@ -11,5 +11,10 @@ cmake .. -G "Visual Studio 17 2022" REM Build the project cmake --build . --config Release -echo Build completed! +if %ERRORLEVEL% EQU 0 ( + echo Build completed successfully! +) else ( + echo Build failed with error level %ERRORLEVEL% +) + cd .. \ No newline at end of file diff --git a/src/crypto.cpp b/src/crypto.cpp index 36654bc..68fd230 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -3,18 +3,24 @@ #include #include -// For now, we'll provide stub implementations -// In a real implementation, you would use a crypto library like Crypto++ or OpenSSL +// Crypto++ includes +#include "cryptlib.h" +#include "osrng.h" // AutoSeededRandomPool +#include "aes.h" // AES encryption +#include "gcm.h" // GCM mode +#include "pwdbased.h" // PBKDF2 +#include "sha.h" // SHA256 +#include "hex.h" // Hex encoder/decoder +#include "zlib.h" // Zlib compression + +using namespace CryptoPP; std::vector Crypto::generate_key(size_t length) { std::vector key(length); - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(0, 255); - for (size_t i = 0; i < length; ++i) { - key[i] = static_cast(dis(gen)); - } + // Use Crypto++ AutoSeededRandomPool for cryptographically secure random numbers + AutoSeededRandomPool rng; + rng.GenerateBlock(key.data(), length); return key; } @@ -23,58 +29,148 @@ std::vector Crypto::encrypt(const std::vector& pla const std::vector& key, const std::vector& iv, std::vector& auth_tag) { - // This is a stub implementation - in a real implementation, - // you would use a proper crypto library like Crypto++ or OpenSSL - // to perform AES-GCM encryption - - // For demonstration purposes, we'll just return the plaintext - // In a real implementation, this would be the actual encryption - auth_tag.resize(16, 0); // 128-bit authentication tag - return plaintext; + try { + // Create GCM mode encryption object + GCM::Encryption encryption; + + // Set key and IV + encryption.SetKeyWithIV(key.data(), key.size(), iv.data(), iv.size()); + + // Prepare output vector + std::vector ciphertext(plaintext.size()); + + // Prepare authentication tag (16 bytes for GCM) + auth_tag.resize(16); + + // Perform encryption + encryption.EncryptAndAuthenticate( + ciphertext.data(), + auth_tag.data(), + auth_tag.size(), + iv.data(), + iv.size(), + nullptr, + 0, // Additional authenticated data + plaintext.data(), + plaintext.size() + ); + + return ciphertext; + } + catch(const Exception& e) { + throw std::runtime_error("Encryption failed: " + std::string(e.what())); + } } std::vector Crypto::decrypt(const std::vector& ciphertext, const std::vector& key, const std::vector& iv, const std::vector& auth_tag) { - // This is a stub implementation - in a real implementation, - // you would use a proper crypto library like Crypto++ or OpenSSL - // to perform AES-GCM decryption - - // For demonstration purposes, we'll just return the ciphertext - // In a real implementation, this would be the actual decryption - return ciphertext; + try { + // Create GCM mode decryption object + GCM::Decryption decryption; + + // Set key and IV + decryption.SetKeyWithIV(key.data(), key.size(), iv.data(), iv.size()); + + // Prepare output vector + std::vector plaintext(ciphertext.size()); + + // Perform decryption and authentication + DecryptionResult result = decryption.DecryptAndVerify( + plaintext.data(), + auth_tag.data(), + auth_tag.size(), + iv.data(), + iv.size(), + nullptr, + 0, // Additional authenticated data + ciphertext.data(), + ciphertext.size() + ); + + if(!result.isValidCoding) { + throw std::runtime_error("Authentication failed during decryption"); + } + + // Resize to actual plaintext size + plaintext.resize(result.messageLength); + + return plaintext; + } + catch(const Exception& e) { + throw std::runtime_error("Decryption failed: " + std::string(e.what())); + } } std::vector Crypto::pbkdf2_hmac_sha256(const std::string& password, const std::vector& salt, int iterations, size_t key_length) { - // This is a stub implementation - in a real implementation, - // you would use a proper crypto library to perform PBKDF2-HMAC-SHA256 - - // For demonstration purposes, we'll just return a key of the requested length - // filled with a simple pattern - std::vector key(key_length, 0); - for (size_t i = 0; i < key_length; i++) { - key[i] = static_cast((i * 17) % 256); + try { + std::vector derived_key(key_length); + + // Use Crypto++ PKCS5_PBKDF2_HMAC for key derivation + PKCS5_PBKDF2_HMAC pbkdf; + pbkdf.DeriveKey( + derived_key.data(), + derived_key.size(), + 0x00, // Purpose byte + reinterpret_cast(password.data()), + password.length(), + salt.data(), + salt.size(), + iterations, + 0.0f // Timeout (0 = no timeout) + ); + + return derived_key; + } + catch(const Exception& e) { + throw std::runtime_error("PBKDF2 key derivation failed: " + std::string(e.what())); } - - return key; } std::vector Crypto::compress(const std::vector& data) { - // This is a stub implementation - in a real implementation, - // you would use zlib or another compression library - - // For demonstration purposes, we'll just return the data as-is - return data; + try { + std::string compressed; + + // Create zlib compressor + ZlibCompressor compressor; + compressor.Put(data.data(), data.size()); + compressor.MessageEnd(); + + // Retrieve compressed data + size_t size = compressor.MaxRetrievable(); + compressed.resize(size); + compressor.Get(reinterpret_cast(&compressed[0]), compressed.size()); + + // Convert to vector + return std::vector(compressed.begin(), compressed.end()); + } + catch(const Exception& e) { + throw std::runtime_error("Compression failed: " + std::string(e.what())); + } } std::vector Crypto::decompress(const std::vector& data) { - // This is a stub implementation - in a real implementation, - // you would use zlib or another decompression library - - // For demonstration purposes, we'll just return the data as-is - return data; + try { + std::string decompressed; + + // Create zlib decompressor + ZlibDecompressor decompressor; + decompressor.Put(data.data(), data.size()); + decompressor.MessageEnd(); + + // Retrieve decompressed data + size_t size = decompressor.MaxRetrievable(); + decompressed.resize(size); + decompressor.Get(reinterpret_cast(&decompressed[0]), decompressed.size()); + + // Convert to vector + return std::vector(decompressed.begin(), decompressed.end()); + } + catch(const Exception& e) { + throw std::runtime_error("Decompression failed: " + std::string(e.what())); + } } \ No newline at end of file