I needed OpenSSL for my Winsock client/server to implement symmetrical encryption/decryption for UDP messages and file data during socket session, for which I send an initial decryption key via socket from client side to server, and server returns a key acknowledgement awaiting further action from client (sendto/recvfrom).
OpenSSL was exactly what I was looking for. It works just fine, uses EVP* functions and utilizes aes256-cbc algorithm using a secret key. Includes 2 functions:
void encrypt(const char *inputString, const unsigned char *key, char *encryptedOutput)
void decrypt(const char *hexString, const unsigned char *key, char **decryptedOutput)
Now, the point was to find a non-MSVCRT version of the libcrypto DLL, and find the static libraries which was available from 3 different online repos and are code signed until June 2024. You just locate a newer copy by that point, and you will also be on a newer OpenSSL version.
The first page I found was at
https://wiki.openssl.org/index.php/BinariesWhich gave me a clear direction. I chose OpenSSL 3.2.0
https://kb.firedaemon.com/support/solutions/articles/4000121705Now in the ZIP contains x86 and x64 versions of the necessary files.
(ZIP) openssl-3/x64/lib/libssl.lib
(ZIP) openssl-3/x64/lib/libcrypto.lib
(ZIP) openssl-3/x64/include/*
(ZIP) openssl-3/x64/bin/libssl-3-x64.dll
Rename "include" directory to "openssl" and place in application path.
Place both libs in same directory as application, and place libssl-3-x64.dll (or libssl-3.dll) in same path too.
#pragma comment(lib, "libssl.lib")
#pragma comment(lib, "libcrypto.lib")
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/conf.h>
Generate the key:
// Init OpenSSL
OpenSSL_add_all_algorithms();
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
unsigned char key[EVP_MAX_KEY_LENGTH];
// Generate random key
if (RAND_bytes(key, sizeof(key)) != 1) {
log_error("Failed to generate random key");
return 0;
}
// Convert the key to a hexadecimal string
char hexKey[(EVP_MAX_KEY_LENGTH * 2) + 1];
for (int i = 0; i < sizeof(key); ++i) {
sprintf(&hexKey[i * 2], "%02x", key[i]);
}
hexKey[sizeof(key) * 2] = '\0';
Encrypting text with same key
char encryptedMessage[512];
encrypt("Some secret text here", (const unsigned char *)hexKey, encryptedMessage);
Decrypting text with same key
char *decryptedData;
decrypt(encryptedMessage, (const unsigned char *)hexKey, &decryptedData);
Encrypt/decrypt functions:
void encrypt(const char *inputString, const unsigned char *key, char *encryptedOutput) {
EVP_CIPHER_CTX *ctx;
int len;
int ciphertextLen;
unsigned char ciphertext[512];
// Create and initialize the context
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, NULL);
// Encrypt the input string
EVP_EncryptUpdate(ctx, ciphertext, &len, (const unsigned char *)inputString, strlen(inputString));
ciphertextLen = len;
// Finalize the encryption
EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
ciphertextLen += len;
// Clean up the context
EVP_CIPHER_CTX_free(ctx);
// Convert the encrypted data to a hexadecimal string
for (int i = 0; i < ciphertextLen; ++i) {
sprintf(&encryptedOutput[i * 2], "%02x", ciphertext[i]);
}
encryptedOutput[ciphertextLen * 2] = '\0';
}
void decrypt(const char *hexString, const unsigned char *key, char **decryptedOutput) {
EVP_CIPHER_CTX *ctx;
int len;
int plaintextLen;
// Create and initialize the context
ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, NULL);
// Convert the hexadecimal string to binary
int hexLen = strlen(hexString);
unsigned char *binaryData = (unsigned char *)malloc(hexLen / 2);
for (int i = 0; i < hexLen / 2; ++i) {
sscanf(&hexString[i * 2], "%2hhx", &binaryData[i]);
}
// Decrypt the binary data
unsigned char *plaintext = (unsigned char *)malloc(hexLen / 2);
EVP_DecryptUpdate(ctx, plaintext, &len, binaryData, hexLen / 2);
plaintextLen = len;
// Finalize the decryption
EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
plaintextLen += len;
// Clean up the context
EVP_CIPHER_CTX_free(ctx);
free(binaryData); // Free the dynamically allocated memory
// Null-terminate the decrypted data
plaintext[plaintextLen] = '\0';
// Assign the decrypted data to the output buffer
*decryptedOutput = (char *)plaintext;
}
Working perfectly for me. In case this helps anyone.