From efe3df7ba8a310849b15b1247addfb6908cc33cf Mon Sep 17 00:00:00 2001 From: Harishankar Date: Tue, 12 May 2020 14:43:40 +0530 Subject: [PATCH] Implemented encryption to obfuscate the grid in puzzle file Implemented encryption while saving the puzzle file for the puzzle grid characters using the master password for key generation. --- wordblah.h | 132 +++++++++++++++++++++++++++++++++++++++++----- wordblah_player.c | 4 +- 2 files changed, 121 insertions(+), 15 deletions(-) diff --git a/wordblah.h b/wordblah.h index 13874dc..f818a7e 100644 --- a/wordblah.h +++ b/wordblah.h @@ -50,7 +50,7 @@ typedef char String[MAX_CLUE_LENGTH]; /* The main puzzle struct type */ typedef struct { - char chars[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; + char chars[MAX_PUZZLE_SIZE+1][MAX_PUZZLE_SIZE+1]; int start_across_word[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; int start_down_word[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; String clue_across[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; @@ -66,7 +66,7 @@ typedef struct { Puzzle puzzle; char filename[65535]; bool is_loaded; - char char_ans[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; + char char_ans[MAX_PUZZLE_SIZE+1][MAX_PUZZLE_SIZE+1]; int cur_row; int cur_col; bool solution_revealed; @@ -103,13 +103,113 @@ err: exit (2); } -/* encode the binary data to readable text format using OpenSSL */ -void encode_binary (char *encoded, unsigned char *binary_data, unsigned int len) +/* encode the binary data to readable text format using OpenSSL - also call + OPENSSL_free if the binary data was allocated by OpenSSL */ +void encode_binary (char *encoded, unsigned char *binary_data, unsigned int len, + bool free_openssl_data) { EVP_EncodeBlock ((unsigned char*)encoded, (const unsigned char*)binary_data, len); - OPENSSL_free (binary_data); + if (free_openssl_data) + OPENSSL_free (binary_data); +} + +/* decode the binary data from the textual representation using OpenSSL */ +void decode_binary (char *bin_data, char *encoded) +{ + EVP_DecodeBlock ((unsigned char*)bin_data, + (const unsigned char*)encoded, strlen (encoded)); +} + +/* encrypt a block of text using password/passphrase with OpenSSL and + also encode it to textual representation */ +void encrypt_data (char *enc_data, const char *data, const char *password) +{ + EVP_CIPHER_CTX *ctx; + int len, cipher_len; + ctx = EVP_CIPHER_CTX_new (); + if (! ctx) goto err; + + unsigned char encrypted[256] = { '\0' }; + + unsigned char key[EVP_MAX_KEY_LENGTH] = { '\0'}; + unsigned char iv[EVP_MAX_IV_LENGTH] = { '\0' }; + + if (! EVP_BytesToKey (EVP_aes_256_cbc(), EVP_md5(), NULL, + (unsigned char*)password, strlen(password), + 10, key, iv)) + goto err; + + if (1 != EVP_EncryptInit_ex (ctx, EVP_aes_256_cbc(), NULL, key, iv)) + goto err; + + if (1 != EVP_EncryptUpdate (ctx, (unsigned char*) encrypted, &len, + (unsigned char*) data, strlen (data) )) + goto err; + cipher_len = len; + + if (1 != EVP_EncryptFinal_ex (ctx, encrypted + len, &len)) + goto err; + + cipher_len += len; + EVP_CIPHER_CTX_free (ctx); + + EVP_EncodeBlock ((unsigned char*) enc_data, (unsigned char*) encrypted, + cipher_len); + return; + err: + ERR_print_errors_fp (stderr); + EVP_CIPHER_CTX_free (ctx); + exit (2); +} + +/* decrypt a block of text using password/passphrase with OpenSSL */ +void decrypt_data (char *dec_data, const char *data, const char *password) +{ + EVP_CIPHER_CTX *ctx; + int len, text_len; + ctx = EVP_CIPHER_CTX_new (); + if (! ctx) goto err; + + char enc_data[256] = { '\0' }; + + unsigned char key[EVP_MAX_KEY_LENGTH] = { '\0'}; + unsigned char iv[EVP_MAX_IV_LENGTH] = { '\0' }; + + + if (! EVP_BytesToKey (EVP_aes_256_cbc(), EVP_md5(), NULL, + (unsigned char*)password, strlen(password), + 10, key, iv)) + goto err; + + int r = EVP_DecodeBlock ((unsigned char*)enc_data, + (const unsigned char*) data, strlen (data)); + if (-1 == r) + goto err; + + + if (1 != EVP_DecryptInit_ex (ctx, EVP_aes_256_cbc(), NULL, key, iv)) + goto err; + + if (1 != EVP_DecryptUpdate (ctx, (unsigned char*) dec_data, &len, + (unsigned char*) enc_data, r - (r % 16) )) + goto err; + text_len = len; + + if (1 != EVP_DecryptFinal_ex (ctx, (unsigned char *)dec_data + len, &len)) + goto err; + + text_len += len; + EVP_CIPHER_CTX_free (ctx); + + dec_data[text_len] = '\0'; + + return; + err: + ERR_print_errors_fp (stderr); + EVP_CIPHER_CTX_free (ctx); + exit (2); } /* get a number from the user */ @@ -134,7 +234,7 @@ bool verify_solution_password (Puzzle *p, const char* password) digest_message ((const unsigned char *)password, strlen(password), &hashed_sol_password, &len); char hashed_hex_pwd[256] = { '\0' }; - encode_binary (hashed_hex_pwd, hashed_sol_password, len); + encode_binary (hashed_hex_pwd, hashed_sol_password, len, true); if (strcmp (p->hashed_solution_password, hashed_hex_pwd) == 0) return true; @@ -156,7 +256,7 @@ bool verify_master_password (Puzzle *p, const char* password) digest_message ((const unsigned char *)password, strlen(password), &hashed_mas_password, &len); char hashed_hex_pwd[256] = { '\0' }; - encode_binary (hashed_hex_pwd, hashed_mas_password, len); + encode_binary (hashed_hex_pwd, hashed_mas_password, len, true); if (strcmp (p->hashed_master_password, hashed_hex_pwd) == 0) return true; @@ -180,7 +280,7 @@ void set_solution_password (Puzzle *p, const char *password) /* the hashedpwd contains binary data - we will convert it to hexadecimal data and store in file */ - encode_binary (p->hashed_solution_password, hashedpwd, len); + encode_binary (p->hashed_solution_password, hashedpwd, len, true); } } @@ -200,7 +300,7 @@ void set_master_password (Puzzle *p, const char *password) /* the hashedpwd contains binary data - we will convert it to hexadecimal data and store in file */ - encode_binary (p->hashed_master_password, hashedpwd, len); + encode_binary (p->hashed_master_password, hashedpwd, len, true); } } @@ -517,11 +617,14 @@ void save_puzzle (Puzzle *puzzle, const char* file) /* the hashed_solution_password */ fprintf (outfile, "%s\n", puzzle->hashed_solution_password); - /* First output the grid characters columns/rows */ + /* First output the grid characters columns/rows as encrypted */ for (int i = 0; i < puzzle->grid_size; i ++) { - for (int j = 0; j < puzzle->grid_size; j ++) - fprintf (outfile, "%c", puzzle->chars[i][j]); + char encrypted[256] = { '\0' }; + encrypt_data (encrypted, puzzle->chars[i], + puzzle->hashed_master_password); + + fprintf (outfile, "%s", encrypted); fprintf (outfile, "\n"); } @@ -670,9 +773,12 @@ Puzzle load_puzzle (const char* file) /* read each character of the grid */ for (int i = 0; i < p.grid_size; i ++ ) { - fgets (line, MAX_CLUE_LENGTH + 10, infile); + char encoded[256]; + fgets (encoded, MAX_CLUE_LENGTH + 10, infile); + decrypt_data (line, encoded, p.hashed_master_password); for (int j = 0; j < p.grid_size; j ++) p.chars[i][j] = line[j]; + } /* read the word numbers */ for (int i = 0; i < p.grid_size; i ++) diff --git a/wordblah_player.c b/wordblah_player.c index 9ca4938..50a1c57 100644 --- a/wordblah_player.c +++ b/wordblah_player.c @@ -57,7 +57,7 @@ gboolean on_down_list_selection_changed (GtkTreeSelection *sel, GtkTreeIter iter; GtkTreeModel* mod; - if (gtk_tree_selection_get_selected (sel, &mod, &iter)) + if (gtk_tree_selection_get_selected (sel, &mod, &iter) == TRUE) { guint sel_word_index; gtk_tree_model_get (mod, &iter, 0, &sel_word_index, -1); @@ -78,7 +78,7 @@ gboolean on_across_list_selection_changed (GtkTreeSelection *sel, GtkTreeIter iter; GtkTreeModel* mod; - if (gtk_tree_selection_get_selected (sel, &mod, &iter)) + if (gtk_tree_selection_get_selected (sel, &mod, &iter) == TRUE) { guint sel_word_index; gtk_tree_model_get (mod, &iter, 0, &sel_word_index, -1); -- 2.20.1