From 528f194c273b02f1ff1e2d9f9e716311afb5d911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Tue, 21 May 2024 09:19:38 +0300 Subject: [PATCH 1/4] hash method has been added --- examples/main.cpp | 14 ++++++++++++ src/libcpp-crypto.hpp | 50 ++++++++++++++++++++++++++++++++++++++++++- test/test.cpp | 9 ++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/examples/main.cpp b/examples/main.cpp index 70c98e1..78469cc 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -214,6 +214,15 @@ void CorruptedTextExceptionWithRSA() } } +void hash() +{ + auto plainText = "This text will be hashed soon"; + + auto hash = CryptoService::hash(plainText); + + std::cout << "Hash: " << hash << std::endl; +} + int main() { // Symmetric Encryption with AES @@ -241,5 +250,10 @@ int main() CorruptedTextExceptionWithRSA(); + + // Hashing + + hash(); + return 0; } diff --git a/src/libcpp-crypto.hpp b/src/libcpp-crypto.hpp index 6c77a36..0c5bc8b 100644 --- a/src/libcpp-crypto.hpp +++ b/src/libcpp-crypto.hpp @@ -1,7 +1,7 @@ /* Modern, easy-to-use, symmetric (AES-256) and asymmetric (RSA) encryption and also hash (SHA-256) library for C++ (17+) -version 1.1.0 +version 1.2.0 https://github.com/leventkaragol/libcpp-crypto If you encounter any issues, please submit a ticket at https://github.com/leventkaragol/libcpp-crypto/issues @@ -37,6 +37,8 @@ SOFTWARE. #include #include #include +#include +#include #include #include #include @@ -442,12 +444,58 @@ namespace lklibs return std::string(plaintext.begin(), plaintext.begin() + outlen); } + /** + * @brief Hashes the given string with SHA-256 + * + * @param text String to hash + * + * @return Hashed string + */ + static std::string hash(const std::string& text) + { + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int lengthOfHash = 0; + + std::unique_ptr context(EVP_MD_CTX_new()); + + if (context) + { + if (EVP_DigestInit_ex(context.get(), EVP_sha256(), nullptr)) + { + if (EVP_DigestUpdate(context.get(), text.c_str(), text.size())) + { + if (EVP_DigestFinal_ex(context.get(), hash, &lengthOfHash)) + { + std::stringstream ss; + + for (unsigned int i = 0; i < lengthOfHash; ++i) + { + ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(hash[i]); + } + + return ss.str(); + } + } + } + } + + return ""; + } + private: struct EVP_CIPHER_CTX_Deleter { void operator()(EVP_CIPHER_CTX* ptr) const { EVP_CIPHER_CTX_free(ptr); } }; + struct EVP_MD_CTX_Deleter + { + void operator()(EVP_MD_CTX* ctx) const + { + EVP_MD_CTX_free(ctx); + } + }; + static int encrypt(const unsigned char* plaintext, int plaintext_len, const unsigned char* key, unsigned char* iv, unsigned char* ciphertext) { std::unique_ptr ctx(EVP_CIPHER_CTX_new()); diff --git a/test/test.cpp b/test/test.cpp index ed6967e..bff3c42 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -331,6 +331,15 @@ TEST(DecryptWithRSATest, DecryptionWithRSAMustBeFailedWithAnCorruptedEncryptedTe } } +TEST(HashTest, HashWithSHA256MustBeCompletedSuccessfully) +{ + std::string plainText = "This text will be hashed soon"; + + auto hashedText = CryptoService::hash(plainText); + + ASSERT_EQ(hashedText, "d32448bab2777b376a5592e384146c3c0182ba589e2521bd0275f2cef6a50546") << "Hash is invalid"; +} + int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); From 1b164fdea4be92c93ebcd6f062eba8e0b90ba9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Tue, 21 May 2024 09:25:00 +0300 Subject: [PATCH 2/4] hash method has been added --- README.md | 26 ++++++++++++++++++++++++++ examples/main.cpp | 4 ++-- test/test.cpp | 4 ++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 387ac08..e069430 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Modern, easy-to-use, symmetric (AES-256) and asymmetric (RSA) encryption and als * [How to use? (Asymmetric Encryption with RSA)](#how-to-use-asymmetric-encryption-with-rsa) * [How do I generate Public/Private Keys?](#how-do-i-generate-publicprivate-keys) * [Relationship between key size and max text length that can be encrypted](#relationship-between-key-size-and-max-text-length-that-can-be-encrypted) +* [How to use? (Hash with SHA-256)](#how-to-use-hash-with-sha-256) * [How to handle Exceptions (AES)?](#how-to-handle-exceptions-aes) * [How to handle Exceptions (RSA)?](#how-to-handle-exceptions-rsa) * [Semantic Versioning](#semantic-versioning) @@ -189,6 +190,29 @@ character sets can take up twice. I am sharing the table below for a quick refer > 4 times more CPU power during encryption/decryption process than the row above. Additionally, generating a 65K bit key takes > time and requires a lot of patience, even for a high-end computer. + +## How to use? (Hash with SHA-256) + +All you need to do is call the static **"hash"** method to hash the given text with SHA-256. + +```cpp +#include "libcpp-crypto.hpp" + +using namespace lklibs; + +int main() { + + std::string plainText = "This text will be hashed soon"; + + auto hashText = CryptoService::hash(plainText); + + std::cout << "Hash: " << hashText << std::endl; + + return 0; +} +``` + + ## How to handle Exceptions (AES)? There are two main Exceptions you may encounter when using the library for AES encryption. The first one is the **"InvalidKeyException"** @@ -325,6 +349,8 @@ static std::string decryptWithAES(const std::string& ciphertext, const std::stri static std::string encryptWithRSA(const std::string& plaintext, const std::string& publicKeyStr); static std::string decryptWithRSA(const std::string& ciphertext, const std::string& privateKeyStr); + +static std::string hash(const std::string& text); ``` ## License diff --git a/examples/main.cpp b/examples/main.cpp index 78469cc..4d2cb8a 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -218,9 +218,9 @@ void hash() { auto plainText = "This text will be hashed soon"; - auto hash = CryptoService::hash(plainText); + auto hashText = CryptoService::hash(plainText); - std::cout << "Hash: " << hash << std::endl; + std::cout << "Hash: " << hashText << std::endl; } int main() diff --git a/test/test.cpp b/test/test.cpp index bff3c42..9258bbb 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -335,9 +335,9 @@ TEST(HashTest, HashWithSHA256MustBeCompletedSuccessfully) { std::string plainText = "This text will be hashed soon"; - auto hashedText = CryptoService::hash(plainText); + auto hashText = CryptoService::hash(plainText); - ASSERT_EQ(hashedText, "d32448bab2777b376a5592e384146c3c0182ba589e2521bd0275f2cef6a50546") << "Hash is invalid"; + ASSERT_EQ(hashText, "d32448bab2777b376a5592e384146c3c0182ba589e2521bd0275f2cef6a50546") << "Hash is invalid"; } int main(int argc, char** argv) From 8124b25a441e29f2a420807f736233e85e2cf1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Tue, 21 May 2024 09:28:01 +0300 Subject: [PATCH 3/4] hash method has been added --- README.md | 49 +++++++++++++++++++++++-------------------------- test/test.cpp | 38 +++++++++++++++++++------------------- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index e069430..af2e9e5 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ Modern, easy-to-use, symmetric (AES-256) and asymmetric (RSA) encryption and als * [How to add it to my project](#how-to-add-it-to-my-project) * [How to use? (Symmetric Encryption with AES)](#how-to-use-symmetric-encryption-with-aes) +* [How to use? (Hash with SHA-256)](#how-to-use-hash-with-sha-256) * [How to use? (Asymmetric Encryption with RSA)](#how-to-use-asymmetric-encryption-with-rsa) * [How do I generate Public/Private Keys?](#how-do-i-generate-publicprivate-keys) * [Relationship between key size and max text length that can be encrypted](#relationship-between-key-size-and-max-text-length-that-can-be-encrypted) -* [How to use? (Hash with SHA-256)](#how-to-use-hash-with-sha-256) * [How to handle Exceptions (AES)?](#how-to-handle-exceptions-aes) * [How to handle Exceptions (RSA)?](#how-to-handle-exceptions-rsa) * [Semantic Versioning](#semantic-versioning) @@ -81,6 +81,27 @@ int main() { > amount of "0" to the end of keys shorter than 32 characters, and ignores the last parts of keys longer than > 32 characters, allowing you to use the key you want without any errors. +## How to use? (Hash with SHA-256) + +All you need to do is call the static **"hash"** method to hash the given text with SHA-256. + +```cpp +#include "libcpp-crypto.hpp" + +using namespace lklibs; + +int main() { + + auto plainText = "This text will be hashed soon"; + + auto hashText = CryptoService::hash(plainText); + + std::cout << "Hash: " << hashText << std::endl; + + return 0; +} +``` + ## How to use? (Asymmetric Encryption with RSA) To encrypt and decrypt the given text with RSA, all you need to do is call the static **"encryptWithRSA"** and @@ -190,29 +211,6 @@ character sets can take up twice. I am sharing the table below for a quick refer > 4 times more CPU power during encryption/decryption process than the row above. Additionally, generating a 65K bit key takes > time and requires a lot of patience, even for a high-end computer. - -## How to use? (Hash with SHA-256) - -All you need to do is call the static **"hash"** method to hash the given text with SHA-256. - -```cpp -#include "libcpp-crypto.hpp" - -using namespace lklibs; - -int main() { - - std::string plainText = "This text will be hashed soon"; - - auto hashText = CryptoService::hash(plainText); - - std::cout << "Hash: " << hashText << std::endl; - - return 0; -} -``` - - ## How to handle Exceptions (AES)? There are two main Exceptions you may encounter when using the library for AES encryption. The first one is the **"InvalidKeyException"** @@ -276,7 +274,7 @@ int main() { The exception part for the RSA side is a little different. If the public and private keys used are not correct, **"InvalidPublicKeyException"** and **"InvalidPrivateKeyException"** are thrown. However, the structure of the keys -used must be corrupt to throw these exceptions. If you use incompatible but structurally valid keys, no exception +used must be corrupt to throw these exceptions. If you use incompatible but structurally valid keys, no exception will be thrown. However, the text obtained after decryption will consist of just meaningless characters. ```cpp @@ -317,7 +315,6 @@ int main() { } ``` - ## Semantic Versioning Versioning of the library is done using conventional semantic versioning. Accordingly, diff --git a/test/test.cpp b/test/test.cpp index 9258bbb..1555882 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -5,8 +5,8 @@ using namespace lklibs; TEST(EncryptWithAESTest, EncryptionWithAESMustBeCompletedSuccessfullyWithAValidKey) { - std::string plainText = "Test message to be used during tests"; - std::string key = "mySecretKey"; + auto plainText = "Test message to be used during tests"; + auto key = "mySecretKey"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); @@ -15,8 +15,8 @@ TEST(EncryptWithAESTest, EncryptionWithAESMustBeCompletedSuccessfullyWithAValidK TEST(DecryptWithAESTest, DecryptionWithAESMustBeCompletedSuccessfullyWithAValidKey) { - std::string plainText = "Test message to be used during tests"; - std::string key = "mySecretKey"; + auto plainText = "Test message to be used during tests"; + auto key = "mySecretKey"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); auto decryptedText = CryptoService::decryptWithAES(encryptedText, key); @@ -26,8 +26,8 @@ TEST(DecryptWithAESTest, DecryptionWithAESMustBeCompletedSuccessfullyWithAValidK TEST(DecryptWithAESTest, DecryptionWithAESMustBeCompletedSuccessfullyForSpecialCharsWithAValidKey) { - std::string plainText = "Test message to be used during tests with special characters: !@#$%^&*()_+{}|:<>?~`-=[]\\;',./öçşığüÖÇŞİĞÜ"; - std::string key = "mySecretKey"; + auto plainText = "Test message to be used during tests with special characters: !@#$%^&*()_+{}|:<>?~`-=[]\\;',./öçşığüÖÇŞİĞÜ"; + auto key = "mySecretKey"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); auto decryptedText = CryptoService::decryptWithAES(encryptedText, key); @@ -37,9 +37,9 @@ TEST(DecryptWithAESTest, DecryptionWithAESMustBeCompletedSuccessfullyForSpecialC TEST(DecryptWithAESTest, DecryptionWithAESMustBeFailedWithAnInvalidKey) { - std::string plainText = "Test message to be used during tests"; - std::string key = "mySecretKey"; - std::string invalidKey = "invalidKey"; + auto plainText = "Test message to be used during tests"; + auto key = "mySecretKey"; + auto invalidKey = "invalidKey"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); @@ -62,7 +62,7 @@ TEST(DecryptWithAESTest, DecryptionWithAESMustBeFailedWithAnInvalidKey) TEST(DecryptWithAESTest, DecryptionWithAESMustBeFailedWithAnCorruptedEncryptedText) { auto encryptedText = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - std::string key = "mySecretKey"; + auto key = "mySecretKey"; try { @@ -82,8 +82,8 @@ TEST(DecryptWithAESTest, DecryptionWithAESMustBeFailedWithAnCorruptedEncryptedTe TEST(AESKeyTest, AESEncryptionShouldBePossibleWithAKeyLessThan32Characters) { - std::string plainText = "Test message to be used during tests"; - std::string key = "123"; + auto plainText = "Test message to be used during tests"; + auto key = "123"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); auto decryptedText = CryptoService::decryptWithAES(encryptedText, key); @@ -93,8 +93,8 @@ TEST(AESKeyTest, AESEncryptionShouldBePossibleWithAKeyLessThan32Characters) TEST(AESKeyTest, AESEncryptionShouldBePossibleWithAKeyLargerThan32Characters) { - std::string plainText = "Test message to be used during tests"; - std::string key = "abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()_+{}|:<>?~`-=[]\\;',./"; + auto plainText = "Test message to be used during tests"; + auto key = "abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()_+{}|:<>?~`-=[]\\;',./"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); auto decryptedText = CryptoService::decryptWithAES(encryptedText, key); @@ -104,8 +104,8 @@ TEST(AESKeyTest, AESEncryptionShouldBePossibleWithAKeyLargerThan32Characters) TEST(AESKeyTest, AESEncryptionShouldBePossibleWithA32CharactersKey) { - std::string plainText = "Test message to be used during tests"; - std::string key = "abcdefghijklmnopqrstuvwxyz123456"; + auto plainText = "Test message to be used during tests"; + auto key = "abcdefghijklmnopqrstuvwxyz123456"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); auto decryptedText = CryptoService::decryptWithAES(encryptedText, key); @@ -115,8 +115,8 @@ TEST(AESKeyTest, AESEncryptionShouldBePossibleWithA32CharactersKey) TEST(AESKeyTest, AESEncryptionMustBePossibleWithAKeyContainingSpecialCharacters) { - std::string plainText = "Test message to be used during tests"; - std::string key = "!@#$%^&*()_+{}|:<>?~`-=[]\\;',./"; + auto plainText = "Test message to be used during tests"; + auto key = "!@#$%^&*()_+{}|:<>?~`-=[]\\;',./"; auto encryptedText = CryptoService::encryptWithAES(plainText, key); auto decryptedText = CryptoService::decryptWithAES(encryptedText, key); @@ -333,7 +333,7 @@ TEST(DecryptWithRSATest, DecryptionWithRSAMustBeFailedWithAnCorruptedEncryptedTe TEST(HashTest, HashWithSHA256MustBeCompletedSuccessfully) { - std::string plainText = "This text will be hashed soon"; + auto plainText = "This text will be hashed soon"; auto hashText = CryptoService::hash(plainText); From ee875bf2c890b681115bf1cf7bc4b728ba220517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Tue, 21 May 2024 09:29:23 +0300 Subject: [PATCH 4/4] hash method has been added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index af2e9e5..9319bcb 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ character sets can take up twice. I am sharing the table below for a quick refer | 65536 | 8181 | > [!IMPORTANT] -> Do not think that you can easily create a longer key to encrypt a longer text with RSA. Each row in the table above consumes +> Do not think that you can easily create a longer key to encrypt a longer text with RSA. Each row in the table consumes > 4 times more CPU power during encryption/decryption process than the row above. Additionally, generating a 65K bit key takes > time and requires a lot of patience, even for a high-end computer.