35 #include <openssl/pem.h>
36 #include <openssl/ssl.h>
37 #include <openssl/rsa.h>
38 #include <openssl/evp.h>
39 #include <openssl/bio.h>
40 #include <openssl/err.h>
45 #pragma clang diagnostic push
46 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
50 RSA *create_rsa(
unsigned char *key,
bool is_public) {
52 BIO *keybio = BIO_new_mem_buf(key, -1);
57 rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
59 rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
68 EVP_PKEY *evpPubKey {};
70 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
72 BIO *bio = BIO_new_mem_buf((
void *)public_key, -1);
74 PEM_read_bio_PUBKEY(bio, &evpPubKey, NULL, NULL);
81 unsigned char *iv =
new unsigned char [EVP_MAX_IV_LENGTH];
84 ek[0] =
new unsigned char [EVP_PKEY_size(evpPubKey)];
86 unsigned char *encMsg =
new unsigned char [message.length() + EVP_MAX_IV_LENGTH];
88 if (!EVP_SealInit(ctx, EVP_aes_256_cbc(), ek, &ek_len, iv, &evpPubKey, 1)) {
89 ERR_load_crypto_strings();
90 HT_FATALF(
"EVP_SealInit() - %s", ERR_error_string(ERR_get_error(), error_buf));
93 if (!EVP_SealUpdate(ctx, encMsg + encMsgLen, &blockLen, (
const unsigned char*)message.c_str(), (int)message.length())) {
94 ERR_load_crypto_strings();
95 HT_FATALF(
"EVP_SealUpdate() - %s", ERR_error_string(ERR_get_error(), error_buf));
97 encMsgLen += blockLen;
99 if(!EVP_SealFinal(ctx, encMsg + encMsgLen, &blockLen)) {
100 ERR_load_crypto_strings();
101 HT_FATALF(
"EVP_SealFinal() - %s", ERR_error_string(ERR_get_error(), error_buf));
103 encMsgLen += blockLen;
105 string encrypted_message;
106 encrypted_message.reserve(2 + ek_len + EVP_MAX_IV_LENGTH + encMsgLen + 1);
110 encrypted_message.append((
const char *)buf, 2);
111 encrypted_message.append((
const char *)ek[0], ek_len);
112 encrypted_message.append((
const char *)iv, EVP_MAX_IV_LENGTH);
113 encrypted_message.append((
const char *)encMsg, encMsgLen);
118 EVP_CIPHER_CTX_free(ctx);
120 return encrypted_message;
125 EVP_PKEY *evpPriKey {};
126 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
128 BIO *bio = BIO_new_mem_buf((
void *)private_key, -1);
130 PEM_read_bio_PrivateKey(bio, &evpPriKey,
nullptr,
nullptr);
134 unsigned char *ek {};
136 unsigned char *iv {};
137 unsigned char *ciphertext {};
138 int ciphertext_len {};
140 const uint8_t *buf = (
const uint8_t *)message.c_str();
141 size_t remain = message.length();
144 ek = (
unsigned char *)buf;
148 iv = (
unsigned char *)buf;
149 buf += EVP_MAX_IV_LENGTH;
150 remain -= EVP_MAX_IV_LENGTH;
152 ciphertext = (
unsigned char *)buf;
153 ciphertext_len = (int)remain;
155 if (EVP_OpenInit(ctx, EVP_aes_256_cbc(), ek, ek_len, iv, evpPriKey) != 1) {
156 ERR_load_crypto_strings();
157 HT_FATALF(
"EVP_OpenInit() - %s", ERR_error_string(ERR_get_error(), error_buf));
161 int plaintext_len {};
162 unsigned char *plaintext =
new unsigned char [ message.length() ];
163 if (EVP_OpenUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len) != 1) {
164 ERR_load_crypto_strings();
165 HT_FATALF(
"EVP_OpenUpdate() - %s", ERR_error_string(ERR_get_error(), error_buf));
169 if (EVP_OpenFinal(ctx, plaintext + len, &len) != 1) {
170 ERR_load_crypto_strings();
171 HT_FATALF(
"EVP_OpenFinal() - %s", ERR_error_string(ERR_get_error(), error_buf));
173 plaintext_len += len;
175 HT_ASSERT(plaintext_len <= (
int)message.length());
177 string decrypted_message;
178 decrypted_message.reserve(plaintext_len+1);
179 decrypted_message.append((
const char *)plaintext, plaintext_len);
182 EVP_CIPHER_CTX_free(ctx);
184 return decrypted_message;
189 const string &message) {
190 RSA *rsa = create_rsa((
unsigned char *)key, key_is_public ? 1 : 0);
192 int buf_len = message.length() + RSA_size(rsa);
193 unsigned char *buf =
new unsigned char [ buf_len ];
196 len = RSA_public_encrypt(message.length(), (
const unsigned char *)message.c_str(), buf, rsa, RSA_PKCS1_PADDING);
198 len = RSA_private_encrypt(message.length(), (
const unsigned char *)message.c_str(), buf, rsa, RSA_PKCS1_PADDING);
202 ERR_load_crypto_strings();
203 HT_FATALF(
"RSA_public_encrypt() - %s", ERR_error_string(ERR_get_error(), ebuf));
205 string encrypted_message;
206 encrypted_message.reserve(len+1);
207 encrypted_message.append((
const char *)buf, len);
210 return encrypted_message;
214 const string &signature) {
215 RSA *rsa = create_rsa((
unsigned char *)key, key_is_public ? 1 : 0);
217 int buf_len = signature.length() + RSA_size(rsa);
218 unsigned char *buf =
new unsigned char [ buf_len ];
221 len = RSA_public_decrypt(signature.length(),
222 (
const unsigned char *)signature.c_str(),
223 buf, rsa, RSA_PKCS1_PADDING);
225 len = RSA_private_decrypt(signature.length(),
226 (
const unsigned char *)signature.c_str(),
227 buf, rsa, RSA_PKCS1_PADDING);
231 ERR_load_crypto_strings();
232 HT_FATALF(
"RSA_public_decrypt() - %s", ERR_error_string(ERR_get_error(), ebuf));
234 string decrypted_message;
235 decrypted_message.reserve(len+1);
236 decrypted_message.append((
const char *)buf, len);
239 return decrypted_message;
242 #pragma clang diagnostic pop
static const string rsa_decrypt(const char *private_key, const string &message)
Decrypts a message with RSA algorithm.
static const string rsa_signature_encrypt(const char *key, bool key_is_public, const string &message)
Computes RSA signature for message.
static const string rsa_encrypt(const char *public_key, const string &message)
Encrypts a message with RSA algorithm.
uint16_t decode_i16(const uint8_t **bufp, size_t *remainp)
Decode a 16-bit integer in little-endian order.
Logging routines and macros.
Compatibility Macros for C/C++.
static const string rsa_signature_decrypt(const char *key, bool key_is_public, const string &signature)
Recovers message from RSA signature.
void encode_i16(uint8_t **bufp, uint16_t val)
Encode a 16-bit integer in little-endian order.
Functions to serialize/deserialize primitives to/from a memory buffer.
#define HT_FATALF(msg,...)