Skip to content

Instantly share code, notes, and snippets.

@sriharshav
Forked from lillypad/rsa.hpp
Created March 17, 2022 23:55
Show Gist options
  • Select an option

  • Save sriharshav/2dac1c634c0dc639f3e7acd754d91e2b to your computer and use it in GitHub Desktop.

Select an option

Save sriharshav/2dac1c634c0dc639f3e7acd754d91e2b to your computer and use it in GitHub Desktop.
OpenSSL RSA Encryption / Decryption C++ Wrapper
// 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