Code:
// gcc -std=c11 -Wall decrypt.c -lssl -lcrypto
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#define PADDING 16
void handleErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}
int decryptFile(const char *inputFile, const char *outputFile, const char *passphrase)
{
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
FILE *inFile = fopen(inputFile, "rb");
if (!inFile) {
perror("Error opening input file");
return 1;
}
FILE *outFile = fopen(outputFile, "wb");
if (!outFile) {
perror("Error opening output file");
fclose(inFile);
return 1;
}
unsigned char salt_buf[9] = {0}, *salt = salt_buf;
fscanf(inFile, "%8s", salt); // skip Salted__
if (strcmp((char*)salt, "Salted__") == 0)
fread(salt, 1, 8, inFile); // store next 8 bytes
else {
rewind(inFile);
salt = NULL;
}
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
const EVP_MD *digest = EVP_sha256();
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
// int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
// const unsigned char *salt,
// const unsigned char *data, int datal, int count,
// unsigned char *key, unsigned char *iv);
if (!EVP_BytesToKey(cipher, digest, salt, (unsigned char*)passphrase,
strlen(passphrase), 1, key, iv)) {
perror("Error deriving key and IV");
fclose(inFile);
fclose(outFile);
return 1;
}
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
perror("Error creating context");
fclose(inFile);
fclose(outFile);
return 1;
}
// int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl,
// const unsigned char *key, const unsigned char *iv);
if (1 != EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv)) {
perror("Error initializing decryption");
EVP_CIPHER_CTX_free(ctx);
fclose(inFile);
fclose(outFile);
return 1;
}
EVP_CIPHER_CTX_set_padding(ctx, PADDING);
unsigned char inBuf[1024], outBuf[sizeof inBuf + PADDING];
int bytesRead, decryptedLen = 0;
while ((bytesRead = fread(inBuf, 1, sizeof inBuf, inFile)) > 0) {
// int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
// int *outl, const unsigned char *in, int inl);
if (1 != EVP_DecryptUpdate(ctx, outBuf, &decryptedLen, inBuf, bytesRead)) {
perror("Error updating decryption");
EVP_CIPHER_CTX_free(ctx);
fclose(inFile);
fclose(outFile);
return 1;
}
fwrite(outBuf, 1, decryptedLen, outFile);
}
// int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
if (1 != EVP_DecryptFinal_ex(ctx, outBuf, &decryptedLen)) {
ERR_print_errors_fp(stderr);
perror("Error finalizing decryption");
EVP_CIPHER_CTX_free(ctx);
fclose(inFile);
fclose(outFile);
return 1;
}
fwrite(outBuf, decryptedLen, 1, outFile);
EVP_CIPHER_CTX_free(ctx);
fclose(inFile);
fclose(outFile);
return 0;
}
int main()
{
const char *inputFile = "encrypted_file.enc";
const char *outputFile = "decrypted_file.txt";
const char *passphrase = "111111";
if (decryptFile(inputFile, outputFile, passphrase) != 0)
fprintf(stderr, "Error decrypting file.\n");
ERR_free_strings();
return 0;
}