-
-
Save sriharshav/2dac1c634c0dc639f3e7acd754d91e2b to your computer and use it in GitHub Desktop.
OpenSSL RSA Encryption / Decryption C++ Wrapper
This file contains hidden or 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
| // c includes | |
| #include <stdio.h> | |
| #include <string.h> | |
| // cpp includes | |
| #include <algorithm> | |
| #include <iostream> | |
| #include <sstream> | |
| // lib includes | |
| #include <openssl/err.h> | |
| #include <openssl/pem.h> | |
| #include <openssl/rsa.h> | |
| #define CRYPTO_PRINT_ERROR fprintf(stderr, "[x] %s\n", strerror(errno)) | |
| class CryptoRSA { | |
| public: | |
| /** | |
| * @brief Construct a new Crypto R S A object | |
| * | |
| * @param rsa_priv_key Private Key | |
| * @param rsa_pub_key Public Key | |
| */ | |
| CryptoRSA(std::string rsa_priv_key, std::string rsa_pub_key) { | |
| if (ReadPublicKeyBuffer((void *)rsa_pub_key.c_str(), rsa_pub_key.size()) == false) { | |
| std::cerr << "Failed to read public key" << std::endl; | |
| } | |
| if (ReadPrivateKeyBuffer((void *)rsa_priv_key.c_str(), rsa_priv_key.size()) == false) { | |
| std::cerr << "Failed to read private key" << std::endl; | |
| } | |
| if (InitPlainText() == false) { | |
| std::cerr << "Failed to initialize plain text" << std::endl; | |
| } | |
| if (InitCipherText() == false) { | |
| std::cerr << "Failed to initialize cypher text" << std::endl; | |
| } | |
| } | |
| /** | |
| * @brief Destroy the Crypto R S A object | |
| * | |
| */ | |
| ~CryptoRSA() { | |
| Cleanup(); | |
| } | |
| /** | |
| * @brief Encrypt using RSA Private key | |
| * | |
| * @param content content to encrypt | |
| * @return std::string encrypted cipher | |
| */ | |
| std::string RSAEncrypt(std::string content) { | |
| PrivateEncrypt((void *)content.c_str(), content.size()); | |
| char *cipherText = (char *)GetCipherText(); | |
| int cipherTextSize = GetCipherTextSize(); | |
| return std::string(cipherText, cipherTextSize); | |
| } | |
| /** | |
| * @brief Decrypt using RSA Public key | |
| * | |
| * @param cipher | |
| * @return std::string | |
| */ | |
| std::string RSADecrypt(std::string cipher) { | |
| PublicDecrypt((void *)cipher.c_str(), cipher.size()); | |
| char *plainText = (char *)GetPlainText(); | |
| int plainTextSize = GetPlainTextSize(); | |
| return std::string(plainText, plainTextSize); | |
| } | |
| /** | |
| * @brief Convert Cypher to Hex String | |
| * | |
| * @param cipher | |
| * @return std::string Hex String | |
| */ | |
| std::string CipherToHexString(std::string cipher) { | |
| static const char *hexDigits = "0123456789ABCDEF"; | |
| std::string hexString; | |
| hexString.reserve(cipher.size() * 2); | |
| std::for_each(cipher.c_str(), cipher.c_str() + cipher.size(), [&hexString](uint8_t cipher_byte) { | |
| hexString.push_back(hexDigits[cipher_byte >> 4]); | |
| hexString.push_back(hexDigits[cipher_byte & 0x0F]); | |
| }); | |
| return hexString; | |
| } | |
| /** | |
| * @brief Convert Hex String to Cypher | |
| * | |
| * @param hex_string | |
| * @return std::string | |
| */ | |
| std::string HexStringToCipher(std::string hex_string) { | |
| auto hexval = [](unsigned char c) { | |
| if ('0' <= c && c <= '9') | |
| return c - '0'; | |
| else if ('a' <= c && c <= 'f') | |
| return c - 'a' + 10; | |
| else if ('A' <= c && c <= 'F') | |
| return c - 'A' + 10; | |
| else | |
| abort(); // un expected from hex string | |
| }; | |
| std::string cipher; | |
| cipher.reserve(hex_string.size() / 2); | |
| for (std::string::const_iterator i = hex_string.begin(); i != hex_string.end(); i++) { | |
| unsigned char c = hexval(*i); | |
| i++; | |
| if (i == hex_string.end()) { | |
| break; | |
| } | |
| c = (c << 4) + hexval(*i); | |
| cipher.push_back(c); | |
| } | |
| return cipher; | |
| } | |
| int RSASign(std::string license, unsigned char *sigret, unsigned int *siglen) { | |
| return RSA_sign(NID_sha256, reinterpret_cast<const unsigned char *>(license.c_str()), license.size(), sigret, siglen, pRSA); | |
| } | |
| int RSAVerify(std::string license, const unsigned char *sigbuf, unsigned int siglen) { | |
| return RSA_verify(NID_sha256, reinterpret_cast<const unsigned char *>(license.c_str()), license.size(), sigbuf, siglen, pRSA); | |
| } | |
| int Get_RSA_size() { | |
| return RSA_size(pRSA); | |
| } | |
| private: | |
| bool ReadPublicKeyBuffer(void *src, size_t src_size) { | |
| FILE *fp = fmemopen(src, src_size, "rb"); | |
| if (fp == NULL) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| if (PEM_read_RSA_PUBKEY(fp, &pRSA, NULL, NULL) == NULL) { | |
| CRYPTO_PRINT_ERROR; | |
| fclose(fp); | |
| return false; | |
| } | |
| fclose(fp); | |
| return true; | |
| } | |
| bool ReadPrivateKeyBuffer(void *src, size_t src_size) { | |
| FILE *fp = fmemopen(src, src_size, "rb"); | |
| if (fp == NULL) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| if (PEM_read_RSAPrivateKey(fp, &pRSA, NULL, NULL) == NULL) { | |
| CRYPTO_PRINT_ERROR; | |
| fclose(fp); | |
| return false; | |
| } | |
| fclose(fp); | |
| return true; | |
| } | |
| void InitKeyPair() { | |
| pRSA = RSA_new(); | |
| } | |
| bool InitPlainText() { | |
| plaintext = malloc(GetCipherTextSize()); | |
| if (plaintext == NULL) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| memset(plaintext, 0, GetCipherTextSize()); | |
| return true; | |
| } | |
| bool InitCipherText() { | |
| ciphertext = malloc(GetCipherTextSize()); | |
| if (ciphertext == NULL) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| memset(ciphertext, 0, GetCipherTextSize()); | |
| return true; | |
| } | |
| void CleanupCipherText() { | |
| free(ciphertext); | |
| } | |
| void CleanupPlainText() { | |
| free(plaintext); | |
| } | |
| void CleanupKeyPair() { | |
| RSA_free(pRSA); | |
| } | |
| void Cleanup() { | |
| CleanupKeyPair(); | |
| CleanupPlainText(); | |
| CleanupCipherText(); | |
| } | |
| bool SetPlainText(void *src, size_t src_size) { | |
| if (src_size > (size_t)GetCipherTextSize()) { | |
| fprintf(stderr, "[x] the data size of %d bytes exceeds the limit of %d bytes\n", (int)src_size, (int)GetCipherTextSize()); | |
| return false; | |
| } | |
| plaintext_size = src_size; | |
| memcpy(plaintext, src, plaintext_size); | |
| return true; | |
| } | |
| bool SetCipherText(void *src, size_t src_size) { | |
| if (src_size > (size_t)GetCipherTextSize()) { | |
| fprintf(stderr, "[x] the data size of %d bytes exceeds the limit of %d bytes\n", (int)src_size, (int)GetCipherTextSize()); | |
| return false; | |
| } | |
| memcpy(ciphertext, src, src_size); | |
| return true; | |
| } | |
| void *GetPlainText() { | |
| return plaintext; | |
| } | |
| int GetPlainTextSize() { | |
| return plaintext_size; | |
| } | |
| void *GetCipherText() { | |
| return ciphertext; | |
| } | |
| int GetCipherTextSize() { | |
| return RSA_size(pRSA); | |
| } | |
| bool PublicEncrypt(void *src, size_t src_size) { | |
| if (SetPlainText(src, src_size) == false) { | |
| return false; | |
| } | |
| int result = RSA_public_encrypt(plaintext_size, (unsigned char *)plaintext, (unsigned char *)ciphertext, pRSA, RSA_PKCS1_PADDING); | |
| if (result < 0) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool PublicDecrypt(void *src, size_t src_size) { | |
| if (SetCipherText(src, src_size) == false) { | |
| return false; | |
| } | |
| int result = RSA_public_decrypt(GetCipherTextSize(), (unsigned char *)ciphertext, (unsigned char *)plaintext, pRSA, RSA_PKCS1_PADDING); | |
| if (result < 0) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| plaintext_size = result; | |
| return true; | |
| } | |
| bool PrivateEncrypt(void *src, size_t src_size) { | |
| if (SetPlainText(src, src_size) == false) { | |
| return false; | |
| } | |
| int result = RSA_private_encrypt(plaintext_size, (unsigned char *)plaintext, (unsigned char *)ciphertext, pRSA, RSA_PKCS1_PADDING); | |
| if (result < 0) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool PrivateDecrypt(void *src, size_t src_size) { | |
| if (SetCipherText(src, src_size) == false) { | |
| return false; | |
| } | |
| int result = RSA_private_decrypt(GetCipherTextSize(), (unsigned char *)ciphertext, (unsigned char *)plaintext, pRSA, RSA_PKCS1_PADDING); | |
| if (result < 0) { | |
| CRYPTO_PRINT_ERROR; | |
| return false; | |
| } | |
| plaintext_size = result; | |
| return true; | |
| } | |
| // variables | |
| void *plaintext; | |
| void *ciphertext; | |
| size_t plaintext_size; | |
| RSA *pRSA; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment