Skip to content

Commit

Permalink
Merge pull request #2629 from verilog-to-routing/rem_warnings
Browse files Browse the repository at this point in the history
Removing warnings from libencrypt and libdecrypt
  • Loading branch information
tangxifan authored Jul 30, 2024
2 parents ddc3ac4 + deb8802 commit 9eef18c
Show file tree
Hide file tree
Showing 11 changed files with 421 additions and 199 deletions.
4 changes: 3 additions & 1 deletion libs/libdecrypt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,6 @@ target_link_libraries(libdecrypt
${OPENSSL_LIBRARIES}
)
install(TARGETS libdecrypt DESTINATION bin)
install(FILES ${LIB_HEADERS} DESTINATION include/libdecrypt)
install(FILES ${LIB_HEADERS} DESTINATION include/libdecrypt)

add_subdirectory(test)
192 changes: 114 additions & 78 deletions libs/libdecrypt/src/decryption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void Decryption::decryptFile() {
"dummykey\n"
"-----END RSA PRIVATE KEY-----\n"); // Replace with your private key string
#endif
RSA* privateKey = loadPrivateKey(privateKeyString);
EVP_PKEY *privateKey = loadPrivateKey(privateKeyString);
if (!privateKey) {
return;
}
Expand All @@ -42,31 +42,27 @@ void Decryption::decryptFile() {
pugi::xml_parse_result result = encryptedDocLoaded.load_file(encryptedFile_.c_str());
if (!result) {
std::cerr << "XML parse error: " << result.description() << std::endl;
RSA_free(privateKey);
EVP_PKEY_free(privateKey);
return;
}

pugi::xml_node root = encryptedDocLoaded.child("EncryptedData");
std::string base64EncryptedSessionKeyLoaded = root.child_value("SessionKey");
std::string base64EncryptedLoaded = root.child_value("Data");

// Base64 decode encrypted session key and data
std::string encryptedSessionKeyLoaded = base64_decode(base64EncryptedSessionKeyLoaded);
std::string encryptedLoaded = base64_decode(base64EncryptedLoaded);

// Decrypt session key
std::string decryptedSessionKey = decryptSessionKey(encryptedSessionKeyLoaded, privateKey);
std::string decryptedSessionKey = decryptSessionKey(base64EncryptedSessionKeyLoaded, privateKey);

// Decrypt XML string
std::string decrypted = decrypt(encryptedLoaded, privateKey);
std::string decrypted = decryptData(base64EncryptedLoaded, reinterpret_cast<const unsigned char*>(decryptedSessionKey.c_str()));

// Write the decrypted data to a file
// std::ofstream decryptedFile("decrypted.xml");
// decryptedFile << decrypted;
// decryptedFile.close();

decryptedContent_ = decrypted;
RSA_free(privateKey);
EVP_PKEY_free(privateKey);
}

/**
Expand All @@ -79,107 +75,147 @@ std::string Decryption::getDecryptedContent() const {
}

/**
* @brief Decrypts the given ciphertext using the provided RSA key.
* @brief Loads the private key from the given PEM string.
*
* @param ciphertext The ciphertext to decrypt.
* @param key The RSA key for decryption.
* @return The decrypted plaintext.
* @param privateKeyString The PEM string representing the private key.
* @return The loaded EVP private key.
*/
std::string Decryption::decrypt(const std::string& ciphertext, RSA* key) {
int rsaLen = RSA_size(key);
int len = ciphertext.size();
std::string plaintext;

for (int i = 0; i < len; i += rsaLen) {
std::vector<unsigned char> buffer(rsaLen);
std::string substr = ciphertext.substr(i, rsaLen);

int result = RSA_private_decrypt(substr.size(), reinterpret_cast<const unsigned char*>(substr.data()), buffer.data(), key, RSA_PKCS1_OAEP_PADDING);
if (result == -1) {
std::cerr << "Decryption error: " << ERR_error_string(ERR_get_error(), NULL) << std::endl;
return "";
}

plaintext.append(reinterpret_cast<char*>(buffer.data()), result);
EVP_PKEY *Decryption::loadPrivateKey(const std::string& privateKeyString) {
EVP_PKEY *pkey = nullptr;
BIO* privateKeyBio = BIO_new_mem_buf(privateKeyString.data(), privateKeyString.size());

if (!privateKeyBio) {
std::cerr << "Error creating BIO for private key" << std::endl;
return nullptr;
}

char* passphrase_cstr = const_cast<char*>(passphrase.c_str());
if (!PEM_read_bio_PrivateKey(privateKeyBio, &pkey, NULL, passphrase_cstr)) {
std::cerr << "Error reading private key" << std::endl;
BIO_free(privateKeyBio);
return nullptr;
}

return plaintext;
BIO_free(privateKeyBio);
return pkey;
}

/**
* @brief Decodes the given base64-encoded string.
* @brief
*
* @param input The base64-encoded input string.
* @return The decoded output string.
* @param encoded The base64-encoded input string.
* @return std::vector<unsigned char> The decoded dynamic array of characters.
*/
std::string Decryption::base64_decode(const std::string& input) {
std::vector<unsigned char> Decryption::base64Decode(const std::string& encoded) {
BIO* bio = BIO_new_mem_buf(encoded.data(), -1);
BIO* b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bio = BIO_push(b64, bio);

BIO* bmem = BIO_new_mem_buf(input.data(), input.size());
b64 = BIO_push(b64, bmem);

std::string output;
output.resize(input.size());

int decoded_size = BIO_read(b64, &output[0], input.size());
output.resize(decoded_size);
BIO_free_all(b64);
std::vector<unsigned char> decoded(encoded.length());
int decodedLen = BIO_read(bio, decoded.data(), encoded.length());
decoded.resize(decodedLen);

return output;
BIO_free_all(bio);
return decoded;
}

/**
* @brief Loads the private key from the given PEM string.
* @brief Decrypts the given encrypted session key using the provided EVP key.
*
* @param privateKeyString The PEM string representing the private key.
* @return The loaded RSA private key.
* @param encryptedSessionKey The encrypted session key.
* @param privateKey The EVP key for decryption.
* @return The decrypted session key.
*/
RSA* Decryption::loadPrivateKey(const std::string& privateKeyString) {
RSA* key = nullptr;
BIO* privateKeyBio = BIO_new_mem_buf(privateKeyString.data(), privateKeyString.size());
std::string Decryption::decryptSessionKey(const std::string& encryptedSessionKey, EVP_PKEY* privateKey) {
std::vector<unsigned char> decodedKey = base64Decode(encryptedSessionKey);

if (!privateKeyBio) {
std::cerr << "Error creating BIO for private key" << std::endl;
return nullptr;
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(privateKey, NULL);
if (!ctx) {
std::cerr << "Failed to create EVP_PKEY_CTX" << std::endl;
return "";
}

if (!PEM_read_bio_RSAPrivateKey(privateKeyBio, &key, NULL, (void*)passphrase.c_str())) {
std::cerr << "Error reading private key" << std::endl;
BIO_free(privateKeyBio);
return nullptr;
if (EVP_PKEY_decrypt_init(ctx) <= 0) {
std::cerr << "EVP_PKEY_decrypt_init failed" << std::endl;
EVP_PKEY_CTX_free(ctx);
return "";
}

BIO_free(privateKeyBio);
return key;
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
std::cerr << "EVP_PKEY_CTX_set_rsa_padding failed" << std::endl;
EVP_PKEY_CTX_free(ctx);
return "";
}

size_t outLen;
if (EVP_PKEY_decrypt(ctx, NULL, &outLen, decodedKey.data(), decodedKey.size()) <= 0) {
std::cerr << "EVP_PKEY_decrypt (determine length) failed" << std::endl;
EVP_PKEY_CTX_free(ctx);
return "";
}

std::vector<unsigned char> out(outLen);
if (EVP_PKEY_decrypt(ctx, out.data(), &outLen, decodedKey.data(), decodedKey.size()) <= 0) {
std::cerr << "EVP_PKEY_decrypt failed" << std::endl;
EVP_PKEY_CTX_free(ctx);
return "";
}

EVP_PKEY_CTX_free(ctx);

return std::string(out.begin(), out.begin() + outLen);
}

/**
* @brief Decrypts the given encrypted session key using the provided RSA key.
* @brief
*
* @param encryptedSessionKey The encrypted session key.
* @param key The RSA key for decryption.
* @return The decrypted session key.
* @param encryptedData The encrypted data to decrypt.
* @param sessionKey The session key for data decryption.
* @return std::string The decrypted plaintext.
*/
std::string Decryption::decryptSessionKey(const std::string& encryptedSessionKey, RSA* key) {
std::vector<unsigned char> decryptedSessionKey(RSA_size(key));
if (RSA_private_decrypt(encryptedSessionKey.size(), reinterpret_cast<const unsigned char*>(encryptedSessionKey.data()), decryptedSessionKey.data(), key, RSA_PKCS1_OAEP_PADDING) == -1) {
std::cerr << "Session key decryption error: " << ERR_error_string(ERR_get_error(), NULL) << std::endl;
std::string Decryption::decryptData(const std::string& encryptedData, const unsigned char* sessionKey) {
std::vector<unsigned char> decodedData = base64Decode(encryptedData);

// Extract the IV from the decoded data
unsigned char iv[EVP_MAX_IV_LENGTH];
int iv_len = EVP_CIPHER_iv_length(EVP_aes_128_cbc());
std::copy(decodedData.begin(), decodedData.begin() + iv_len, iv);
const unsigned char* ciphertext = decodedData.data() + iv_len;
size_t ciphertextLen = decodedData.size() - iv_len;

EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
std::cerr << "Failed to create EVP_CIPHER_CTX" << std::endl;
return "";
}

return std::string(reinterpret_cast<char*>(decryptedSessionKey.data()), decryptedSessionKey.size());
}
if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, sessionKey, iv) != 1) {
std::cerr << "EVP_DecryptInit_ex failed" << std::endl;
EVP_CIPHER_CTX_free(ctx);
return "";
}

std::vector<unsigned char> plaintext(ciphertextLen + EVP_CIPHER_block_size(EVP_aes_128_cbc()));
int len = 0;
int plaintextLen = 0;

// int main(int argc, char* argv[]) {
// if (argc < 2) {
// std::cerr << "Usage: " << argv[0] << " <encrypted file> <public key>\n";
// return -1;
// }
if (EVP_DecryptUpdate(ctx, plaintext.data(), &len, ciphertext, ciphertextLen) != 1) {
std::cerr << "EVP_DecryptUpdate failed" << std::endl;
EVP_CIPHER_CTX_free(ctx);
return "";
}
plaintextLen += len;

// std::string encryptedFile = argv[1];
if (EVP_DecryptFinal_ex(ctx, plaintext.data() + plaintextLen, &len) != 1) {
std::cerr << "EVP_DecryptFinal_ex failed" << std::endl;
EVP_CIPHER_CTX_free(ctx);
return "";
}
plaintextLen += len;
plaintext.resize(plaintextLen);

// Decryption decryption(encryptedFile);
EVP_CIPHER_CTX_free(ctx);

// return 0;
// }
return std::string(plaintext.begin(), plaintext.end());
}
29 changes: 15 additions & 14 deletions libs/libdecrypt/src/decryption.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <iostream>
#include <sstream>
#include <vector>
Expand Down Expand Up @@ -49,38 +50,38 @@ class Decryption
std::string decryptedContent_; /**< The decrypted content of the file. */

/**
* @brief Decrypts the given ciphertext using the provided RSA key.
* @brief
*
* @param ciphertext The ciphertext to decrypt.
* @param key The RSA key for decryption.
* @return The decrypted plaintext.
* @param encryptedData The encrypted data to decrypt.
* @param sessionKey The session key for data decryption.
* @return std::string The decrypted plaintext.
*/
static std::string decrypt(const std::string &ciphertext, RSA *key);
static std::string decryptData(const std::string& encryptedData, const unsigned char* sessionKey);

/**
* @brief Decodes the given base64-encoded string.
* @brief
*
* @param input The base64-encoded input string.
* @return The decoded output string.
* @param encoded he base64-encoded input string.
* @return std::vector<unsigned char> The decoded dynamic array of characters.
*/
static std::string base64_decode(const std::string &input);
static std::vector<unsigned char> base64Decode(const std::string& encoded);

/**
* @brief Loads the private key from the given PEM string.
*
* @param privateKeyString The PEM string representing the private key.
* @return The loaded RSA private key.
* @return The loaded EVP private key.
*/
static RSA *loadPrivateKey(const std::string &privateKeyString);
static EVP_PKEY* loadPrivateKey(const std::string& privateKeyString);

/**
* @brief Decrypts the given encrypted session key using the provided RSA key.
* @brief Decrypts the given encrypted session key using the provided EVP key.
*
* @param encryptedSessionKey The encrypted session key.
* @param key The RSA key for decryption.
* @param privateKey The EVP key for decryption.
* @return The decrypted session key.
*/
static std::string decryptSessionKey(const std::string &encryptedSessionKey, RSA *key);
static std::string decryptSessionKey(const std::string& encryptedSessionKey, EVP_PKEY* privateKey);
};

#endif // DECRYPTION_H
21 changes: 21 additions & 0 deletions libs/libdecrypt/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.10)
project(EncryptionDecryptionTest)

# Find OpenSSL
find_package(OpenSSL REQUIRED)

add_executable(test_encrypt_decrypt src/test.cpp src/main.cpp)

set(PUBLIC_KEY_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../libencrypt/public_key.pem")
target_compile_definitions(test_encrypt_decrypt PRIVATE PUBLIC_KEY_FILE="${PUBLIC_KEY_FILE_PATH}")

include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../libencrypt/src"
"${CMAKE_CURRENT_SOURCE_DIR}/../src"
"${CMAKE_CURRENT_SOURCE_DIR}/src")

target_link_libraries(test_encrypt_decrypt
libpugixml
libdecrypt
libencrypt)

add_test(NAME test_encrypt_decrypt COMMAND test_encrypt_decrypt)
33 changes: 33 additions & 0 deletions libs/libdecrypt/test/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "test.h"

int main() {
std::string testFilePath = "test.xml";
std::string publicKeyFile = PUBLIC_KEY_FILE; // Path to your public key file
std::string encryptedFilePath = "test.xmle";

// Step 1: Create a test XML file
createTestXMLFile(testFilePath);

std::string originalContent = readFileToString(testFilePath);

// Step 2: Encrypt XML content
Encryption encryption;
if (!encryption.encryptFile(publicKeyFile, testFilePath)) {
std::cerr << "Encryption failed" << std::endl;
return 1;
}

// Step 3: Decrypt XML content
Decryption decryption(encryptedFilePath);
std::string decryptedContent = decryption.getDecryptedContent();

// Step 4: Compare original XML content with decrypted XML content
if (decryptedContent == originalContent) {
std::cout << "Test passed: Decrypted content matches original content" << std::endl;
} else {
std::cerr << "Test failed: Decrypted content does not match original content" << std::endl;
return 1;
}

return 0;
}
Loading

0 comments on commit 9eef18c

Please sign in to comment.