Skip to content

Instantly share code, notes, and snippets.

@lillypad
Last active March 8, 2024 13:10
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save lillypad/f5de36cd9769cfaa54af80b4b331184e to your computer and use it in GitHub Desktop.
Save lillypad/f5de36cd9769cfaa54af80b4b331184e to your computer and use it in GitHub Desktop.
OpenSSL RSA Encryption / Decryption C++ Wrapper
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#define CRYPTO_RSA_KEY_LEN_4096 4096
#define CRYPTO_RSA_KEY_LEN_2048 2048
#define CRYPTO_RSA_KEY_LEN_1024 1024
#define CRYPTO_RSA_KEY_EXP 65535
#define CRYPTO_PRINT_ERROR fprintf(stderr, "[x] %s\n", strerror(errno))
using namespace std;
class CryptoRSA{
public:
bool GenerateKeys(int key_length){
SetKeyLength(key_length);
pRSA = RSA_generate_key(GetKeyLength(), CRYPTO_RSA_KEY_EXP, NULL, NULL);
if (RSA_check_key(pRSA) != 1){
CRYPTO_PRINT_ERROR;
return false;
}
return true;
}
void SetKeyLength(int key_length){
keylen = key_length;
}
int GetKeyLength(){
return keylen;
}
bool WritePublicKeyFile(char * key_public){
FILE *fp = fopen(key_public, "w");
if (fp == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (PEM_write_RSAPublicKey(fp, pRSA) == 0){
CRYPTO_PRINT_ERROR;
return false;
}
fclose(fp);
return true;
}
bool WritePrivateKeyFile(char *key_private){
FILE *fp = fopen(key_private, "w");
if (fp == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (PEM_write_RSAPrivateKey(fp, pRSA, NULL, NULL, 0, NULL, NULL) == 0){
CRYPTO_PRINT_ERROR;
return false;
}
return true;
}
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_RSAPublicKey(fp, &pRSA, NULL, NULL) == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
fclose(fp);
return true;
}
bool ReadPublicKeyFile(char *key_public){
FILE *fp = fopen(key_public, "rb");
if (fp == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (PEM_read_RSAPublicKey(fp, &pRSA, NULL, NULL) == NULL){
CRYPTO_PRINT_ERROR;
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;
return false;
}
fclose(fp);
return true;
}
bool ReadPrivateKeyFile(char *key_private){
FILE *fp = fopen(key_private, "rb");
if (fp == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (PEM_read_RSAPrivateKey(fp, &pRSA, NULL, NULL) == NULL){
CRYPTO_PRINT_ERROR;
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 Initialize(){
InitKeyPair();
InitPlainText();
InitCipherText();
}
void InitBuffers(){
InitPlainText();
InitCipherText();
}
void Cleanup(){
CleanupKeyPair();
CleanupPlainText();
CleanupCipherText();
}
void CleanupBuffers(){
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;
}
RSA *GetRSABlob(){
return pRSA;
}
int GetCipherTextSize(){
return RSA_size(pRSA);
}
void DebugCipherText(){
hex_dump((char *)"ciphertext", ciphertext, GetCipherTextSize());
}
void DebugPlainText(){
hex_dump((char *)"plaintext", plaintext, plaintext_size);
}
bool WriteCipherTextFile(char *ciphertext_file){
FILE *fp = fopen(ciphertext_file, "wb");
if (fp == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (fwrite(ciphertext, GetCipherTextSize(), 1, fp) <= 0){
CRYPTO_PRINT_ERROR;
return false;
}
fclose(fp);
return true;
}
bool WritePlainTextFile(char *plaintext_file){
FILE *fp_decrypted = fopen(plaintext_file, "wb");
if (fp_decrypted == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (fwrite(plaintext, GetPlainTextSize(), 1, fp_decrypted) <= 0){
CRYPTO_PRINT_ERROR;
return false;
}
fclose(fp_decrypted);
return true;
}
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;
}
bool ReadPlainTextFile(char *plaintext_file){
FILE *fp_plaintext = fopen(plaintext_file, "rb");
if (fp_plaintext == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (file_size(fp_plaintext) > GetCipherTextSize()){
fprintf(stderr,
"[x] the data size of %d bytes exceeds the limit of %d bytes\n",
file_size(fp_plaintext),
GetCipherTextSize());
return false;
}
if (fread(plaintext, file_size(fp_plaintext), 1, fp_plaintext) <= 0){
CRYPTO_PRINT_ERROR;
return false;
}
plaintext_size = file_size(fp_plaintext);
fclose(fp_plaintext);
return true;
}
bool ReadCipherTextFile(char *ciphertext_file){
FILE *fp_encrypted = fopen(ciphertext_file, "rb");
if (fp_encrypted == NULL){
CRYPTO_PRINT_ERROR;
return false;
}
if (fread(ciphertext, GetCipherTextSize(), 1, fp_encrypted) <= 0){
CRYPTO_PRINT_ERROR;
return false;
}
fclose(fp_encrypted);
return true;
}
bool PrivateDecryptFile(char *encrypted_file, char *decrypted_file){
if (ReadCipherTextFile(encrypted_file) == false){
return false;
}
if (PrivateDecrypt(ciphertext, GetCipherTextSize()) == false){
return false;
}
if (WritePlainTextFile(decrypted_file) == false){
return false;
}
return true;
}
bool PublicDecryptFile(char *encrypted_file, char *decrypted_file){
if (ReadCipherTextFile(encrypted_file) == false){
return false;
}
if (PublicDecrypt(ciphertext, GetCipherTextSize()) == false){
return false;
}
if (WritePlainTextFile(decrypted_file) == false){
return false;
}
return true;
}
private:
void hex_dump(char *desc, void *addr, size_t len){
int i;
unsigned char buff[17];
const unsigned char *pc = (const unsigned char*)addr;
if (desc != NULL){
printf ("%s:\n", desc);
}
for (i = 0; i < (int)len; i++) {
if ((i % 16) == 0) {
if (i != 0){
printf (" %s\n", buff);
}
printf (" %04x ", i);
}
printf (" %02x", pc[i]);
if ((pc[i] < 0x20) || (pc[i] > 0x7e)){
buff[i % 16] = '.';
} else{
buff[i % 16] = pc[i];
}
buff[(i % 16) + 1] = '\0';
}
while ((i % 16) != 0){
printf (" ");
i++;
}
printf (" %s\n", buff);
}
int file_size(FILE *fp){
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
int sz=ftell(fp);
fseek(fp,prev,SEEK_SET);
return sz;
}
void *plaintext;
void *ciphertext;
int keylen;
size_t plaintext_size;
RSA *pRSA;
};
@mcordova1967
Copy link

Thank you for sharing this code, thanks to this I managed to make a password database encoder/decoder for my json server using pub & priv keys. Regards

@reston21rob
Copy link

Can someone briefly explain how to use this class? I would really like to use this implementation in my project but I need a short explanation on how to use it. I'm sorry for such a trivial question, but I'm just starting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment