Skip to content

Commit

Permalink
Merge pull request #10 from leventkaragol/hash
Browse files Browse the repository at this point in the history
Hash
  • Loading branch information
leventkaragol authored May 21, 2024
2 parents ee7367d + ee875bf commit c953a9e
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 22 deletions.
29 changes: 26 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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)
Expand Down Expand Up @@ -80,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
Expand Down Expand Up @@ -185,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.
Expand Down Expand Up @@ -252,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
Expand Down Expand Up @@ -293,7 +315,6 @@ int main() {
}
```


## Semantic Versioning

Versioning of the library is done using conventional semantic versioning. Accordingly,
Expand Down Expand Up @@ -325,6 +346,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
Expand Down
14 changes: 14 additions & 0 deletions examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,15 @@ void CorruptedTextExceptionWithRSA()
}
}

void hash()
{
auto plainText = "This text will be hashed soon";

auto hashText = CryptoService::hash(plainText);

std::cout << "Hash: " << hashText << std::endl;
}

int main()
{
// Symmetric Encryption with AES
Expand Down Expand Up @@ -241,5 +250,10 @@ int main()

CorruptedTextExceptionWithRSA();


// Hashing

hash();

return 0;
}
50 changes: 49 additions & 1 deletion src/libcpp-crypto.hpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -37,6 +37,8 @@ SOFTWARE.
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <string>
#include <iomanip>
#include <sstream>
#include <vector>
#include <memory>
#include <array>
Expand Down Expand Up @@ -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<EVP_MD_CTX, EVP_MD_CTX_Deleter> 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<int>(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<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Deleter> ctx(EVP_CIPHER_CTX_new());
Expand Down
45 changes: 27 additions & 18 deletions test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -62,7 +62,7 @@ TEST(DecryptWithAESTest, DecryptionWithAESMustBeFailedWithAnInvalidKey)
TEST(DecryptWithAESTest, DecryptionWithAESMustBeFailedWithAnCorruptedEncryptedText)
{
auto encryptedText = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
std::string key = "mySecretKey";
auto key = "mySecretKey";

try
{
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -331,6 +331,15 @@ TEST(DecryptWithRSATest, DecryptionWithRSAMustBeFailedWithAnCorruptedEncryptedTe
}
}

TEST(HashTest, HashWithSHA256MustBeCompletedSuccessfully)
{
auto plainText = "This text will be hashed soon";

auto hashText = CryptoService::hash(plainText);

ASSERT_EQ(hashText, "d32448bab2777b376a5592e384146c3c0182ba589e2521bd0275f2cef6a50546") << "Hash is invalid";
}

int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
Expand Down

0 comments on commit c953a9e

Please sign in to comment.