From b9dac186aba864c92c378791e269594d0660e84b Mon Sep 17 00:00:00 2001 From: afonso Date: Fri, 23 Feb 2024 10:36:23 +0000 Subject: [PATCH] [c] Implemented the cfich_aes_ctr.c file Reads passphrase from stdin Encrypt stores salt+iv+ciphertext in the output Decrypt reads the salt,iv,and ciphertext and uses those values --- TPs/TP02/c/src/cfich_aes_ctr.c | 247 +++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 TPs/TP02/c/src/cfich_aes_ctr.c diff --git a/TPs/TP02/c/src/cfich_aes_ctr.c b/TPs/TP02/c/src/cfich_aes_ctr.c new file mode 100644 index 0000000..39fb77f --- /dev/null +++ b/TPs/TP02/c/src/cfich_aes_ctr.c @@ -0,0 +1,247 @@ +#include +#include +#include +#include +#include +#include + +#define KEY_SIZE 32 +#define SALT_SIZE 16 +#define ITERATIONS 10000 + +int aes_ctr(const char *input_file, const char *output_file, const unsigned char *key, int enc) { + + int BUF_SIZE = 1024; + int cipher_block_size = EVP_CIPHER_block_size(EVP_aes_256_ctr()); + + int input_size = BUF_SIZE; + int output_size = input_size + (cipher_block_size - 1); + int u_len = 0, f_len = 0; + + unsigned char input_buf[input_size], output_buf[output_size]; + + FILE *finput = fopen(input_file, "rb"); + if (finput == NULL) { + fprintf(stderr, "Error opening input file\n"); + return 1; + } + + // Open output file + FILE *foutput = fopen(output_file, "ab"); + if (foutput == NULL) { + fprintf(stderr, "Error opening output file\n"); + fclose(finput); + return 1; + } + + EVP_CIPHER_CTX *ctx = NULL; + if (!(ctx = EVP_CIPHER_CTX_new())) { + fprintf(stderr, "Error creating context\n"); + fclose(finput); + fclose(foutput); + return 1; + } + + // If enc is 1, then we are encrypting, else we are decrypting + // If we are encrypting, we need to generate an IV + // If we are decrypting, we need to read the IV from the file + unsigned char iv[16]; + if (enc) { + if (RAND_bytes(iv, 16) != 1) { + fprintf(stderr, "Error generating IV\n"); + return 1; + } + if (fwrite(iv, 1, 16, foutput) != 16) { + fprintf(stderr, "Error writing IV to file\n"); + return 1; + } + } else { + // Seek forward by 16 bytes to ignore the salt + if (fseek(finput, 16, SEEK_SET) != 0) { + fprintf(stderr, "Error seeking to IV position in input file\n"); + return 1; + } + if (fread(iv, 1, 16, finput) != 16) { + fprintf(stderr, "Error reading IV from file\n"); + return 1; + } + } + + if (EVP_CipherInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, iv, enc) != 1) { + fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + EVP_CIPHER_CTX_free(ctx); + return 1; + } + + int read_size, len; + while ((read_size = fread(input_buf, 1, BUF_SIZE, finput)) > 0) { + printf("Read %d bytes, passing through CipherUpdate...\n", read_size); + if (EVP_CipherUpdate(ctx, output_buf, &len, input_buf, read_size) != 1) { + fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + fclose(finput); + fclose(foutput); + return 1; + } + printf("\tGot back %d bytes from CipherUpdate...\n", len); + printf("Writing %d bytes to %s...\n", len, output_file); + if (fwrite(output_buf, 1, len, foutput) != len) { + fprintf(stderr, "Error writing to output file\n"); + return 1; + } + printf("\tWrote %d bytes\n", len); + u_len += len; + } + if (read_size == -1) { + fprintf(stderr, "ERROR: Reading from the file %s failed.\n", input_file); + } + + if (EVP_CipherFinal_ex(ctx, output_buf, &f_len) != 1) { + fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + fclose(finput); + fclose(foutput); + return 1; + } + printf("u_len: %d, f_len: %d\n", u_len, f_len); + + if (f_len) { + printf("Writing final %d bytes to %s...\n", f_len, output_file); + if (fwrite(output_buf, 1, f_len, foutput) != f_len) { + fprintf(stderr, "Error writing to output file\n"); + fclose(finput); + fclose(foutput); + return 1; + } + } + printf("\tWrote last %d bytes\n", f_len); + fclose(finput); + fclose(foutput); + + return 0; +} + +int encrypt(char *input_file, const char *passphrase) { + unsigned char key[KEY_SIZE]; + unsigned char salt[SALT_SIZE]; + // Derive key from passphrase using PBKDF2 + char *output_file = malloc(strlen(input_file) + 5); + strcpy(output_file, input_file); + strcat(output_file, ".enc"); + + if (RAND_bytes(salt, SALT_SIZE) != 1) { + fprintf(stderr, "Error generating salt\n"); + return 1; + } + // Write salt to output file + FILE *foutput = fopen(output_file, "wb"); + if (foutput == NULL) { + fprintf(stderr, "Error opening output file\n"); + return 1; + } + if (fwrite(salt, 1, 16, foutput) != 16) { + fprintf(stderr, "Error writing salt to file\n"); + return 1; + } + fclose(foutput); + + // Derive key from passphrase using PBKDF2 + if (PKCS5_PBKDF2_HMAC(passphrase, strlen(passphrase), salt, SALT_SIZE, ITERATIONS, EVP_sha256(), + KEY_SIZE, key) != 1) { + fprintf(stderr, "Error deriving key from passphrase\n"); + return 1; + } + + // Print salt and key + printf("Salt: "); + for (int i = 0; i < SALT_SIZE; i++) { + printf("%02x", salt[i]); + } + printf("\n"); + printf("Key: "); + for (int i = 0; i < KEY_SIZE; i++) { + printf("%02x", key[i]); + } + printf("\n"); + + aes_ctr(input_file, output_file, key, 1); + return 0; +} + +int decrypt(char *input_file, const char *passphrase) { + unsigned char key[KEY_SIZE]; + unsigned char salt[SALT_SIZE]; + // Derive key from passphrase using PBKDF2 + char *output_file = malloc(strlen(input_file) + 5); + strcpy(output_file, input_file); + strcat(output_file, ".dec"); + // Read salt from input file + FILE *finput = fopen(input_file, "rb"); + if (finput == NULL) { + fprintf(stderr, "Error opening input file\n"); + return 1; + } + if (fread(salt, 1, 16, finput) != 16) { + fprintf(stderr, "Error reading salt from file\n"); + return 1; + } + fclose(finput); + + // Derive key from passphrase using PBKDF2 + if (PKCS5_PBKDF2_HMAC(passphrase, strlen(passphrase), salt, SALT_SIZE, ITERATIONS, EVP_sha256(), + KEY_SIZE, key) != 1) { + fprintf(stderr, "Error deriving key from passphrase\n"); + return 1; + } + + // Print salt and key + printf("Salt: "); + for (int i = 0; i < SALT_SIZE; i++) { + printf("%02x", salt[i]); + } + printf("\n"); + printf("Key: "); + for (int i = 0; i < KEY_SIZE; i++) { + printf("%02x", key[i]); + } + printf("\n"); + + aes_ctr(input_file, output_file, key, 0); + return 0; +} + +int main(int argc, char *argv[]) { + if (argc < 3) { + fprintf(stderr, "Usage: %s {enc|dec} [file_path]\n", argv[0]); + return 1; + } + + char *mode = argv[1]; + char *input_file = argv[2]; + + if (!(strcmp(mode, "enc") == 0 || strcmp(mode, "dec") == 0)) { + fprintf(stderr, "Invalid mode. Use 'enc' or 'dec'.\n"); + } + + if (argc != 3) { + fprintf(stderr, "Usage: %s {enc|dec} [file_path]\n", argv[0]); + return 1; + } + input_file = argv[2]; + + char passphrase[256]; // Assuming maximum passphrase length of 255 characters + printf("Enter passphrase: "); + if (fgets(passphrase, sizeof(passphrase), stdin) == NULL) { + fprintf(stderr, "Error reading passphrase from stdin\n"); + return 1; + } + passphrase[strcspn(passphrase, "\n")] = '\0'; // Remove trailing newline + + if (strcmp(mode, "enc") == 0) { + encrypt(input_file, passphrase); + } else { + decrypt(input_file, passphrase); + } + return 0; +}