-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from coders-school/encryption
Encryption
- Loading branch information
Showing
16 changed files
with
420 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
cmake_minimum_required(VERSION 3.14) | ||
|
||
# # Basic Files | ||
file(GLOB project_src | ||
"symCrypt/*.cpp" | ||
"hash/*.cpp" | ||
) | ||
|
||
project(encrpyt) | ||
|
||
option(USE_SYSTEM_OPENSSL "Use the system's OpenSSL if available" OFF) | ||
|
||
include(FindPackageHandleStandardArgs) | ||
find_package(OpenSSL QUIET) | ||
if(NOT OpenSSL_FOUND) | ||
if(USE_SYSTEM_OPENSSL) | ||
message(FATAL_ERROR "System OpenSSL not found. Set USE_SYSTEM_OPENSSL to OFF or install OpenSSL.") | ||
else() | ||
set(OPENSSL_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl-src) # default path by CMake | ||
set(OPENSSL_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl) | ||
set(OPENSSL_INCLUDE_DIR ${OPENSSL_INSTALL_DIR}/include) | ||
set(OPENSSL_CONFIGURE_COMMAND ${OPENSSL_SOURCE_DIR}/config) | ||
include(ExternalProject) | ||
ExternalProject_Add( | ||
OpenSSL | ||
SOURCE_DIR ${OPENSSL_SOURCE_DIR} | ||
GIT_REPOSITORY https://github.com/openssl/openssl.git | ||
GIT_TAG openssl-3.2.1 | ||
USES_TERMINAL_DOWNLOAD TRUE | ||
CONFIGURE_COMMAND | ||
${OPENSSL_CONFIGURE_COMMAND} | ||
--prefix=${OPENSSL_INSTALL_DIR} | ||
--openssldir=${OPENSSL_INSTALL_DIR} | ||
BUILD_COMMAND make | ||
TEST_COMMAND "" | ||
INSTALL_COMMAND make install | ||
INSTALL_DIR ${OPENSSL_INSTALL_DIR} | ||
) | ||
|
||
file(MAKE_DIRECTORY ${OPENSSL_INCLUDE_DIR}) | ||
|
||
add_library(OpenSSL::SSL STATIC IMPORTED GLOBAL) | ||
set_property(TARGET OpenSSL::SSL PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libssl.${OPENSSL_LIBRARY_SUFFIX}) | ||
set_property(TARGET OpenSSL::SSL PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR}) | ||
add_dependencies(OpenSSL::SSL OpenSSL) | ||
|
||
add_library(OpenSSL::Crypto STATIC IMPORTED GLOBAL) | ||
set_property(TARGET OpenSSL::Crypto PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libcrypto.${OPENSSL_LIBRARY_SUFFIX}) | ||
set_property(TARGET OpenSSL::Crypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR}) | ||
add_dependencies(OpenSSL::Crypto OpenSSL) | ||
endif() | ||
endif() | ||
|
||
add_library(encrpyt ${project_src}) | ||
target_link_libraries(encrpyt PUBLIC OpenSSL::SSL OpenSSL::Crypto) | ||
target_include_directories(encrpyt PUBLIC "../") | ||
target_compile_options(encrpyt PRIVATE -Wall -Wextra -Wpedantic -Werror) | ||
|
||
if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MODERN_CMAKE_BUILD_TESTING) AND(BUILD_TESTING)) | ||
enable_testing() | ||
add_subdirectory(uTests) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# encrypt | ||
|
||
`encrypt` is a straightforward wrapper library built on top of the OpenSSL library, offering implementations of cryptographic algorithms such as SHA-512 hashing and AES-256-CBC encryption. | ||
|
||
## Features | ||
|
||
- Efficient implementation of SHA-512 hashing. | ||
- Implementation of AES-256-CBC encryption with OpenSSL. | ||
- Utilizes `std::span` for handling input and output data efficiently. | ||
|
||
## Usage | ||
|
||
### SHA512 | ||
|
||
To compute the SHA-512 hash of a message, you can use the `SHA512` class: | ||
|
||
```cpp | ||
#include "encrypt/hash/SHA512.hpp" | ||
|
||
using namespace encrypt; | ||
|
||
int main() { | ||
std::string message = "Hello, World!"; | ||
SHA512 sha512; | ||
std::string hash = sha512.hash({message.begin(), message.end()}); | ||
std::cout << "SHA-512 hash of '" << message << "': " << hash << std::endl; | ||
return 0; | ||
} | ||
``` | ||
### AES256CBC | ||
To perform AES-256-CBC encryption and decryption, you can use the `AES256CBC` class: | ||
|
||
```cpp | ||
#include "encrypt/symCrypt/AES256CBC.hpp" | ||
|
||
using namespace encrypt; | ||
|
||
int main() { | ||
std::string key = "YourKeyHere"; | ||
std::string iv = "YourInitializationVectorHere"; | ||
AES256CBC aes256cbc({iv.begin(), iv.end()}); | ||
|
||
std::string plaintext = "YourPlainTextHere"; | ||
std::string ciphertext(plaintext.size() + AES_BLOCK_SIZE, '\0'); | ||
|
||
// Encryption | ||
aes256cbc.encrypt(key, {plaintext.begin(), plaintext.end()}, {ciphertext.begin(), ciphertext.end()}); | ||
std::cout << "Encrypted text: " << ciphertext << std::endl; | ||
|
||
// Decryption | ||
std::string decryptedtext(plaintext.size(), '\0'); | ||
aes256cbc.decrypt(key, {ciphertext.begin(), ciphertext.end()}, {decryptedtext.begin(), decryptedtext.end()}); | ||
std::cout << "Decrypted text: " << decryptedtext << std::endl; | ||
|
||
return 0; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include "FakeHash.hpp" | ||
using namespace encrypt; | ||
|
||
std::string FakeHash::hash(std::span<const unsigned char> input) const { | ||
return std::string(input.begin(), input.end()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
#include "IHash.hpp" | ||
|
||
namespace encrypt { | ||
class FakeHash : public IHash { | ||
public: | ||
std::string hash(std::span<const unsigned char> input) const override; | ||
}; | ||
} // namespace encrypt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
#include <span> | ||
#include <string> | ||
|
||
namespace encrypt { | ||
class IHash { | ||
public: | ||
virtual ~IHash() = default; | ||
virtual std::string hash(std::span<const unsigned char> input) const = 0; | ||
}; | ||
} // namespace encrypt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#include "SHA512.hpp" | ||
|
||
#include <openssl/evp.h> | ||
#include <openssl/sha.h> | ||
|
||
#include <memory> | ||
#include <stdexcept> | ||
#include <vector> | ||
|
||
using namespace encrypt; | ||
|
||
using EVP_MD_CTX_ptr = | ||
std::unique_ptr<EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>; | ||
|
||
std::string SHA512::hash(std::span<const unsigned char> input) const { | ||
EVP_MD_CTX_ptr ctx(EVP_MD_CTX_new(), ::EVP_MD_CTX_free); | ||
if (!ctx) { | ||
throw std::runtime_error("Error creating EVP_MD_CTX"); | ||
} | ||
if (!EVP_DigestInit_ex(ctx.get(), EVP_sha512(), nullptr)) { | ||
throw std::runtime_error("Error initializing SHA-512 digest"); | ||
} | ||
if (!EVP_DigestUpdate(ctx.get(), input.data(), input.size())) { | ||
throw std::runtime_error("Error updating SHA-512 digest"); | ||
} | ||
std::vector<unsigned char> hash(SHA512_DIGEST_LENGTH); | ||
if (!EVP_DigestFinal_ex(ctx.get(), hash.data(), nullptr)) { | ||
throw std::runtime_error("Error finalizing SHA-512 digest"); | ||
} | ||
return std::string(hash.begin(), hash.end()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
#include "IHash.hpp" | ||
|
||
namespace encrypt { | ||
class SHA512 : public IHash { | ||
public: | ||
std::string hash(std::span<const unsigned char> input) const override; | ||
}; | ||
} // namespace encrypt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#include "AES256CBC.hpp" | ||
|
||
#include <openssl/aes.h> | ||
#include <openssl/evp.h> | ||
|
||
#include <memory> | ||
|
||
using namespace encrypt; | ||
|
||
using EVP_CIPHER_CTX_t = | ||
std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>; | ||
|
||
AES256CBC::AES256CBC(std::span<const unsigned char> iv) : iv(iv) {} | ||
|
||
void AES256CBC::encrypt(const std::string &key, | ||
std::span<const unsigned char> plainText, | ||
std::span<unsigned char> &cipherText) const { | ||
size_t blockSize = EVP_CIPHER_block_size(EVP_aes_256_cbc()); | ||
size_t paddingSize = blockSize - (plainText.size() % blockSize); | ||
size_t expectedSize = plainText.size() + paddingSize; | ||
if (cipherText.size() < expectedSize) { | ||
throw std::runtime_error("cipherText buffer is too small"); | ||
} | ||
EVP_CIPHER_CTX_t ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free); | ||
int res{}, outlen{}; | ||
size_t totalOut{0}; | ||
res = EVP_EncryptInit(ctx.get(), EVP_aes_256_cbc(), | ||
reinterpret_cast<const unsigned char *>(key.c_str()), | ||
iv.data()); | ||
if (res != 1) { | ||
throw std::runtime_error("Error in EVP_EncryptInit"); | ||
} | ||
res = EVP_EncryptUpdate(ctx.get(), cipherText.data(), &outlen, | ||
plainText.data(), plainText.size()); | ||
if (res != 1) { | ||
throw std::runtime_error("Error in EVP_EncryptUpdate"); | ||
} | ||
totalOut += outlen; | ||
res = EVP_EncryptFinal(ctx.get(), cipherText.data() + totalOut, &outlen); | ||
if (res != 1) { | ||
throw std::runtime_error("Error in EVP_EncryptFinal"); | ||
} | ||
totalOut += outlen; | ||
cipherText = cipherText.first(totalOut); | ||
} | ||
|
||
void AES256CBC::decrypt(const std::string &key, | ||
std::span<const unsigned char> cipherText, | ||
std::span<unsigned char> &plainText) const { | ||
size_t expectedSize = cipherText.size(); | ||
if (plainText.size() < expectedSize) { | ||
throw std::runtime_error("plainText buffer is too small"); | ||
} | ||
EVP_CIPHER_CTX_t ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free); | ||
int res{}, outlen{}; | ||
size_t totalOut{0}; | ||
res = EVP_DecryptInit(ctx.get(), EVP_aes_256_cbc(), | ||
reinterpret_cast<const unsigned char *>(key.c_str()), | ||
iv.data()); | ||
if (res != 1) { | ||
throw std::runtime_error("Error in EVP_DecryptInit"); | ||
} | ||
res = EVP_DecryptUpdate(ctx.get(), plainText.data(), &outlen, | ||
cipherText.data(), cipherText.size()); | ||
if (res != 1) { | ||
throw std::runtime_error("Error in EVP_DecryptUpdate"); | ||
} | ||
totalOut += outlen; | ||
|
||
res = EVP_DecryptFinal(ctx.get(), plainText.data() + totalOut, &outlen); | ||
if (res != 1) { | ||
throw std::runtime_error("Error in EVP_DecryptFinal"); | ||
} | ||
totalOut += outlen; | ||
plainText = plainText.first(totalOut); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
#include "ISymCipher.hpp" | ||
|
||
namespace encrypt { | ||
class AES256CBC : public ISymCipher { | ||
public: | ||
explicit AES256CBC(std::span<const unsigned char> iv); | ||
|
||
void encrypt(const std::string& key, std::span<const unsigned char> plainText, | ||
std::span<unsigned char>& secret) const override; | ||
|
||
void decrypt(const std::string& key, std::span<const unsigned char> secret, | ||
std::span<unsigned char>& plainText) const override; | ||
|
||
private: | ||
std::span<const unsigned char> iv; | ||
}; | ||
} // namespace encrypt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#include "FakeSymCipher.hpp" | ||
|
||
#include <algorithm> | ||
#include <stdexcept> | ||
|
||
using namespace encrypt; | ||
|
||
void FakeSymCipher::encrypt(const std::string& /* key */, | ||
std::span<const unsigned char> plainText, | ||
std::span<unsigned char>& cipherText) const { | ||
if (cipherText.size() < plainText.size()) { | ||
throw std::runtime_error("cipherText buffer is too small"); | ||
} | ||
std::copy(plainText.begin(), plainText.end(), cipherText.begin()); | ||
} | ||
|
||
void FakeSymCipher::decrypt(const std::string& /* key */, | ||
std::span<const unsigned char> cipherText, | ||
std::span<unsigned char>& plainText) const { | ||
if (plainText.size() < cipherText.size()) { | ||
throw std::runtime_error("plainText buffer is too small"); | ||
} | ||
std::copy(cipherText.begin(), cipherText.end(), plainText.begin()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
#include "ISymCipher.hpp" | ||
|
||
namespace encrypt { | ||
class FakeSymCipher : public ISymCipher { | ||
public: | ||
void encrypt(const std::string& key, std::span<const unsigned char> plainText, | ||
std::span<unsigned char>& secret) const override; | ||
|
||
void decrypt(const std::string& key, std::span<const unsigned char> secret, | ||
std::span<unsigned char>& plainText) const override; | ||
}; | ||
} // namespace encrypt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
|
||
#include <span> | ||
#include <string> | ||
|
||
namespace encrypt { | ||
struct ISymCipher { | ||
virtual ~ISymCipher() = default; | ||
virtual void encrypt(const std::string &key, | ||
std::span<const unsigned char> plainText, | ||
std::span<unsigned char> &cipherText) const = 0; | ||
|
||
virtual void decrypt(const std::string &key, | ||
std::span<const unsigned char> cipherText, | ||
std::span<unsigned char> &plainText) const = 0; | ||
}; | ||
} // namespace encrypt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
include(FetchContent) | ||
|
||
set(TEST_NAME ${PROJECT_NAME}-UT) | ||
|
||
FetchContent_Declare( | ||
googletest | ||
GIT_REPOSITORY "https://github.com/google/googletest.git" | ||
GIT_TAG release-1.11.0 | ||
) | ||
|
||
FetchContent_MakeAvailable(googletest) | ||
|
||
file(GLOB_RECURSE test_src | ||
"*.cpp" | ||
) | ||
|
||
add_executable(${TEST_NAME} ${test_src}) | ||
target_link_libraries(${TEST_NAME} gtest_main ${PROJECT_NAME}) | ||
set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") | ||
|
||
include(GoogleTest) | ||
gtest_discover_tests(${TEST_NAME}) |
Oops, something went wrong.