From 651730e3cb8b25e1fbae7e7370619c8faa13bb3c Mon Sep 17 00:00:00 2001
From: Adrian Tarver <21149460+Th3Tr1ckst3r@users.noreply.github.com>
Date: Mon, 23 Dec 2024 19:18:58 +0000
Subject: [PATCH] Add files via upload
Signed-off-by: Adrian Tarver <21149460+Th3Tr1ckst3r@users.noreply.github.com>
---
gaius_v1.1.c | 565 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 565 insertions(+)
create mode 100644 gaius_v1.1.c
diff --git a/gaius_v1.1.c b/gaius_v1.1.c
new file mode 100644
index 0000000..4b26ff6
--- /dev/null
+++ b/gaius_v1.1.c
@@ -0,0 +1,565 @@
+/*
+ Gaius - A cryptography tool which implements a new complex mixed substitution
+ cipher dubbed 'Gaius Cipher' into binary/plaintext data structures.
+
+ Created by Adrian Tarver(Th3Tr1ckst3r) @ https://github.com/Th3Tr1ckst3r/
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+ IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+
+ By downloading, copying, installing, or using the software you agree to this license.
+ If you do not agree to this license, do not download, install,
+ copy, or use the software.
+
+
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow here:
+
+https://raw.githubusercontent.com/Th3Tr1ckst3r/Gaius/main/LICENSE
+*/
+
+#include // For stat, mkdir, and struct stat.
+#include // For errno.
+#include // For working with directories.
+#include
+#include
+#include
+#include
+#include
+#include
+#include // For access() to check file existence.
+
+#define ALPHABET "abcdefghijklmnopqrstuvwxyz"
+#define PUNCTUATION "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
+#define DEFAULT_BUFFER_SIZE 4096
+
+// Function declarations.
+char *base64_encode(const unsigned char *data, size_t input_length);
+char *base64_decode(const char *encoded_data, size_t *decoded_length);
+void generate_mixed_alphabet(const char *keyword, char *mixed_alphabet, char *punctuation_mapping);
+void encipher(const char *input, const char *mixed_alphabet, const char *punctuation_mapping, char *output);
+void decipher(const char *input, const char *mixed_alphabet, const char *punctuation_mapping, char *output);
+int find_index(const char *str, char ch);
+void process_text(const char *input, const char *mapping, const char *reverse_mapping, char *output);
+int validate_password(const char *password);
+int is_directory(const char *path);
+void create_directory(const char *path);
+void process_directory(const char *mode, const char *keyword, const char *input_dir, const char *output_dir, const char *mixed_alphabet, const char *punctuation_mapping, int disable_base64, int enable_verbosity, int buffer_size);
+void process_file(const char *mode, const char *keyword, const char *input_file, const char *output_file, const char *mixed_alphabet, const char *punctuation_mapping, int disable_base64, int enable_verbosity, int buffer_size);
+
+// Function to encode data in Base64.
+const char *b64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+// Function to encode raw data in Base64.
+char *base64_encode(const unsigned char *data, size_t input_length) {
+ size_t output_length = 4 * ((input_length + 2) / 3); // Output length must be 4 times the size of input
+ char *encoded_data = malloc(output_length + 1); // +1 for null terminator
+
+ if (encoded_data == NULL) return NULL; // Error checking for malloc failure
+
+ for (size_t i = 0, j = 0; i < input_length;) {
+ unsigned long octet_a = i < input_length ? (unsigned char)data[i++] : 0;
+ unsigned long octet_b = i < input_length ? (unsigned char)data[i++] : 0;
+ unsigned long octet_c = i < input_length ? (unsigned char)data[i++] : 0;
+
+ unsigned long triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+ encoded_data[j++] = b64_table[(triple >> 3 * 6) & 0x3F];
+ encoded_data[j++] = b64_table[(triple >> 2 * 6) & 0x3F];
+ encoded_data[j++] = b64_table[(triple >> 1 * 6) & 0x3F];
+ encoded_data[j++] = b64_table[(triple >> 0 * 6) & 0x3F];
+ }
+
+ // Add padding if necessary
+ for (int i = 0; i < 3 - (input_length % 3); i++) {
+ encoded_data[output_length - 1 - i] = '=';
+ }
+
+ encoded_data[output_length] = '\0'; // Null-terminate the string
+ return encoded_data;
+}
+
+// Function to decode Base64 data into raw data.
+char *base64_decode(const char *encoded_data, size_t *decoded_length) {
+ size_t len = strlen(encoded_data);
+ *decoded_length = (len / 4) * 3; // The decoded length is 3/4 of the encoded length
+
+ // Handle padding '=' characters
+ if (encoded_data[len - 1] == '=') (*decoded_length)--;
+ if (encoded_data[len - 2] == '=') (*decoded_length)--;
+
+ char *decoded_data = malloc(*decoded_length); // Allocate memory for the decoded data
+ if (decoded_data == NULL) {
+ perror("Failed to allocate memory for decoded data");
+ return NULL;
+ }
+
+ int i = 0, j = 0;
+ unsigned char a, b, c, d;
+
+ // Loop through the encoded data in 4-character blocks
+ while (i < len) {
+ a = strchr(b64_table, encoded_data[i++]) - b64_table;
+ b = strchr(b64_table, encoded_data[i++]) - b64_table;
+ c = strchr(b64_table, encoded_data[i++]) - b64_table;
+ d = strchr(b64_table, encoded_data[i++]) - b64_table;
+
+ decoded_data[j++] = (a << 2) | (b >> 4);
+ if (encoded_data[i - 2] != '=') decoded_data[j++] = (b << 4) | (c >> 2);
+ if (encoded_data[i - 1] != '=') decoded_data[j++] = (c << 6) | d;
+ }
+
+ return decoded_data;
+}
+
+// wrapper for better utilization of our encoding function.
+char *encode_data_to_base64(const unsigned char *data, size_t input_length) {
+ return base64_encode(data, input_length);
+}
+
+// wrapper for better utilization of our decoding function.
+char *decode_base64_data(const char *encoded_data, size_t *decoded_length) {
+ return base64_decode(encoded_data, decoded_length);
+}
+
+// Function to generate a mixed alphabet based on the keyword.
+void generate_mixed_alphabet(const char *keyword, char *mixed_alphabet, char *punctuation_mapping) {
+ int i, j = 0, used[26] = {0};
+ size_t keyword_len = strlen(keyword);
+ char unique_chars[26] = {0};
+ int punctuation_len = strlen(PUNCTUATION);
+
+ // Initialize mixed alphabet to empty string
+ mixed_alphabet[0] = '\0';
+
+ // Add unique characters from the keyword to mixed alphabet
+ for (i = 0; i < keyword_len; i++) {
+ char ch = tolower(keyword[i]);
+ if (isalpha(ch) && !used[ch - 'a']) {
+ mixed_alphabet[j++] = ch;
+ used[ch - 'a'] = 1;
+ }
+ }
+
+ // Append remaining characters from the alphabet
+ for (i = 0; i < 26; i++) {
+ if (!used[i]) {
+ mixed_alphabet[j++] = ALPHABET[i];
+ }
+ }
+ mixed_alphabet[j] = '\0';
+
+ // Create punctuation mapping by shuffling punctuation characters
+ for (i = 0; i < punctuation_len; i++) {
+ punctuation_mapping[i] = PUNCTUATION[i];
+ }
+ // Shuffle punctuation mapping randomly
+ srand(time(NULL)); // Seed random number generator
+ for (i = punctuation_len - 1; i > 0; i--) {
+ int rand_idx = rand() % (i + 1);
+ char temp = punctuation_mapping[i];
+ punctuation_mapping[i] = punctuation_mapping[rand_idx];
+ punctuation_mapping[rand_idx] = temp;
+ }
+}
+
+// Function to encipher text using mixed alphabet and punctuation mapping.
+void encipher(const char *input, const char *mixed_alphabet, const char *punctuation_mapping, char *output) {
+ size_t i, len = strlen(input);
+ for (i = 0; i < len; i++) {
+ char ch = input[i];
+ if (isalpha(ch)) {
+ int index = strchr(ALPHABET, tolower(ch)) - ALPHABET;
+ output[i] = isupper(ch) ? toupper(mixed_alphabet[index]) : mixed_alphabet[index];
+ } else if (strchr(PUNCTUATION, ch)) {
+ int index = strchr(PUNCTUATION, ch) - PUNCTUATION;
+ output[i] = punctuation_mapping[index];
+ } else {
+ output[i] = ch; // Non-alphabetic characters are unchanged
+ }
+ }
+ output[i] = '\0';
+}
+
+// Function to decipher text using mixed alphabet and punctuation mapping.
+void decipher(const char *input, const char *mixed_alphabet, const char *punctuation_mapping, char *output) {
+ size_t i, len = strlen(input);
+ for (i = 0; i < len; i++) {
+ char ch = input[i];
+ if (isalpha(ch)) {
+ int index = strchr(mixed_alphabet, tolower(ch)) - mixed_alphabet;
+ output[i] = isupper(ch) ? toupper(ALPHABET[index]) : ALPHABET[index];
+ } else if (strchr(punctuation_mapping, ch)) {
+ int index = strchr(punctuation_mapping, ch) - punctuation_mapping;
+ output[i] = PUNCTUATION[index];
+ } else {
+ output[i] = ch; // Non-alphabetic characters are unchanged
+ }
+ }
+ output[i] = '\0';
+}
+
+// Function to find the index of a character in a string.
+int find_index(const char *str, char ch) {
+ char *ptr = strchr(str, ch);
+ return (ptr) ? (ptr - str) : -1;
+}
+
+// Function to process text for enciphering, or deciphering.
+void process_text(const char *input, const char *mapping, const char *reverse_mapping, char *output) {
+ size_t i, len = strlen(input);
+ for (i = 0; i < len; i++) {
+ char ch = input[i];
+
+ // Handle alphabetic characters (both uppercase and lowercase)
+ if (isalpha(ch)) {
+ int index = find_index(mapping, tolower(ch));
+ if (index != -1) {
+ output[i] = isupper(ch) ? toupper(reverse_mapping[index]) : reverse_mapping[index];
+ }
+ }
+ // Handle punctuation characters
+ else if (strchr(PUNCTUATION, ch)) {
+ int index = find_index(mapping, ch);
+ if (index != -1) {
+ output[i] = reverse_mapping[index];
+ } else {
+ output[i] = ch; // If punctuation isn't mapped, just copy the character
+ }
+ }
+ // For other characters (spaces, newlines, etc.), leave them unchanged
+ else {
+ output[i] = ch;
+ }
+ }
+ output[i] = '\0'; // Null-terminate the output string
+}
+
+// Function to validate the keyword/password.
+int validate_password(const char *password) {
+ int has_special = 0, has_digit = 0, length = strlen(password);
+
+ if (length < 8) {
+ return 0; // Password too short
+ }
+
+ for (int i = 0; i < length; i++) {
+ if (isdigit(password[i])) {
+ has_digit = 1;
+ }
+ if (!isalnum(password[i])) { // Checks for non-alphanumeric (special characters)
+ has_special = 1;
+ }
+ }
+
+ return has_special && has_digit;
+}
+
+// Function to check if a path is a directory.
+int is_directory(const char *path) {
+ struct stat path_stat;
+ if (stat(path, &path_stat) != 0) {
+ return 0; // Path does not exist or error
+ }
+ return S_ISDIR(path_stat.st_mode);
+}
+
+// Function to create a directory if it doesn't exist.
+void create_directory(const char *path) {
+ if (mkdir(path, 0755) != 0 && errno != EEXIST) {
+ perror("Failed to create output directory");
+ exit(1);
+ }
+}
+
+// Function to process a single file.
+void process_file(const char *mode, const char *keyword, const char *input_file, const char *output_file,
+ const char *mixed_alphabet, const char *punctuation_mapping, int disable_base64, int enable_verbosity, int buffer_size) {
+ if (enable_verbosity) {
+ printf("Processing file: %s\n", input_file);
+ printf("Output file: %s\n", output_file);
+ printf("Mode: %s\n", mode);
+ printf("Base64 Encoding Disabled: %s\n", disable_base64 ? "Yes" : "No");
+ printf("Buffer Size: %d bytes\n", buffer_size);
+ }
+
+ // Open input and output files
+ FILE *input_fp = fopen(input_file, "rb");
+ if (!input_fp) {
+ perror("Error opening input file");
+ return;
+ }
+
+ FILE *output_fp = fopen(output_file, "wb");
+ if (!output_fp) {
+ perror("Error opening output file");
+ fclose(input_fp);
+ return;
+ }
+
+ unsigned char *buffer = malloc(buffer_size);
+ unsigned char *processed_buffer = malloc(buffer_size * 2); // Allocate for worst-case size
+ if (!buffer || !processed_buffer) {
+ perror("Memory allocation failed for buffers");
+ free(buffer);
+ free(processed_buffer);
+ fclose(input_fp);
+ fclose(output_fp);
+ return;
+ }
+
+ size_t bytes_read, bytes_processed;
+
+ while ((bytes_read = fread(buffer, 1, buffer_size, input_fp)) > 0) {
+ if (strcmp(mode, "encipher") == 0) {
+ if (!disable_base64) {
+ // Encode input to Base64 before ciphering
+ char *encoded_data = base64_encode(buffer, bytes_read);
+ if (!encoded_data) {
+ fprintf(stderr, "Failed to encode data for file: %s\n", input_file);
+ break;
+ }
+ process_text(encoded_data, mixed_alphabet, ALPHABET, (char *)processed_buffer);
+ fwrite(processed_buffer, 1, strlen((char *)processed_buffer), output_fp);
+ free(encoded_data);
+ } else {
+ // Cipher directly without Base64
+ process_text((char *)buffer, mixed_alphabet, ALPHABET, (char *)processed_buffer);
+ fwrite(processed_buffer, 1, bytes_read, output_fp);
+ }
+ } else if (strcmp(mode, "decipher") == 0) {
+ if (!disable_base64) {
+ // Decipher the text
+ process_text((char *)buffer, ALPHABET, mixed_alphabet, (char *)processed_buffer);
+
+ // Decode Base64 after ciphering
+ size_t decoded_length;
+ char *decoded_data = base64_decode((char *)processed_buffer, &decoded_length);
+ if (!decoded_data) {
+ fprintf(stderr, "Failed to decode data for file: %s\n", input_file);
+ break;
+ }
+ fwrite(decoded_data, 1, decoded_length, output_fp);
+ free(decoded_data);
+ } else {
+ // Decipher directly without Base64
+ process_text((char *)buffer, ALPHABET, mixed_alphabet, (char *)processed_buffer);
+ fwrite(processed_buffer, 1, bytes_read, output_fp);
+ }
+ } else {
+ fprintf(stderr, "Error: Invalid mode for file: %s\n", input_file);
+ break;
+ }
+
+ if (enable_verbosity) {
+ printf("Processed %zu bytes from input file.\n", bytes_read);
+ }
+ }
+
+ if (enable_verbosity) {
+ printf("File processing complete. Output written to: %s\n", output_file);
+ }
+
+ // Cleanup
+ free(buffer);
+ free(processed_buffer);
+ fclose(input_fp);
+ fclose(output_fp);
+}
+
+// Recursive function to process a directory.
+void process_directory(const char *mode, const char *keyword, const char *input_dir, const char *output_dir,
+ const char *mixed_alphabet, const char *punctuation_mapping, int disable_base64, int enable_verbosity, int buffer_size) {
+ if (enable_verbosity) {
+ printf("Processing directory: %s\n", input_dir);
+ printf("Output directory: %s\n", output_dir);
+ }
+
+ // Open the input directory
+ DIR *dir = opendir(input_dir);
+ if (!dir) {
+ perror("Failed to open input directory");
+ exit(1);
+ }
+
+ struct dirent *entry;
+ while ((entry = readdir(dir)) != NULL) {
+ // Skip "." and ".." entries
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+ continue;
+ }
+
+ char input_path[1024], output_path[1024];
+ snprintf(input_path, sizeof(input_path), "%s/%s", input_dir, entry->d_name);
+ snprintf(output_path, sizeof(output_path), "%s/%s", output_dir, entry->d_name);
+
+ if (is_directory(input_path)) {
+ // Process subdirectory
+ if (enable_verbosity) {
+ printf("Found directory: %s\n", input_path);
+ printf("Creating output directory: %s\n", output_path);
+ }
+ create_directory(output_path);
+ process_directory(mode, keyword, input_path, output_path, mixed_alphabet, punctuation_mapping, disable_base64, enable_verbosity, buffer_size);
+ } else {
+ // Process file
+ if (enable_verbosity) {
+ printf("Found file: %s\n", input_path);
+ }
+ process_file(mode, keyword, input_path, output_path, mixed_alphabet, punctuation_mapping, disable_base64, enable_verbosity, buffer_size);
+ }
+ }
+
+ if (enable_verbosity) {
+ printf("Finished processing directory: %s\n", input_dir);
+ }
+
+ closedir(dir);
+}
+
+// Main function to process arguments.
+int main(int argc, char *argv[]) {
+ int disable_base64 = 0;
+ int enable_verbosity = 0;
+ int buffer_size = DEFAULT_BUFFER_SIZE;
+
+ // Parse optional flags
+ for (int i = 5; i < argc; i++) {
+ if (strcmp(argv[i], "-n64") == 0) {
+ disable_base64 = 1;
+ } else if (strcmp(argv[i], "-v") == 0) {
+ enable_verbosity = 1;
+ } else if (strcmp(argv[i], "-chunk") == 0) {
+ // Ensure a value follows the "-chunk" flag
+ if (i + 1 < argc) {
+ buffer_size = atoi(argv[++i]); // Convert the next argument to an integer
+ if (buffer_size <= 0) {
+ fprintf(stderr, "Error: Invalid buffer size '%s'. Must be a positive integer.\n", argv[i]);
+ return 1;
+ }
+ // Ensure the buffer_size is at least 1024 bytes
+ if (buffer_size < 1024) {
+ fprintf(stderr, "Error: Buffer size cannot be less than 1024 bytes. Setting to 1024 bytes.\n");
+ buffer_size = 1024;
+ }
+ } else {
+ fprintf(stderr, "Error: Missing value for '-chunk' flag.\n");
+ return 1;
+ }
+ } else {
+ fprintf(stderr, "Error: Unknown flag '%s'.\n", argv[i]);
+ return 1;
+ }
+ }
+
+ // Validate argument count
+ if (argc < 5) {
+ fprintf(stderr,
+ "Gaius V1.0 - A cryptography tool which implements a new complex mixed substitution cipher dubbed 'Gaius Cipher' into binary/plaintext data structures.\n\n\n"
+ "Usage: gaius [-n64, -v, -chunk ]\n\n"
+ "Optional Usage: \n\n"
+ "-n64 Disables utilization of base64 in the cipher process.\n"
+ "-v Enables verbose output for debugging.\n"
+ "-chunk Specifies the buffer size for processing files (default: 4096 bytes).\n\n"
+ "For more information, including documentation, please visit https://www.github.com/Th3Tr1ckst3r/Gaius\n\n");
+ return 1;
+ }
+
+ const char *mode = argv[1];
+ const char *keyword = argv[2];
+ const char *input_path = argv[3];
+ const char *output_path = argv[4];
+
+ if (!validate_password(keyword)) {
+ fprintf(stderr, "Error: Password must be at least 8 characters long, contain at least 1 special character, and 1 integer.\n");
+ return 1;
+ }
+
+ if (!is_directory(input_path) && access(input_path, F_OK) == -1) {
+ fprintf(stderr, "Error: Input path does not exist.\n");
+ return 1;
+ }
+
+ if (is_directory(output_path)) {
+ create_directory(output_path);
+ }
+
+ char mixed_alphabet[27];
+ char punctuation_mapping[strlen(PUNCTUATION) + 1];
+ generate_mixed_alphabet(keyword, mixed_alphabet, punctuation_mapping);
+
+ if (enable_verbosity) {
+ printf("Mode: %s\n", mode);
+ printf("Keyword: %s\n", keyword);
+ printf("Input Path: %s\n", input_path);
+ printf("Output Path: %s\n", output_path);
+ printf("Disable Base64: %s\n", disable_base64 ? "Yes" : "No");
+ printf("Verbosity Enabled: Yes\n");
+ printf("Buffer Size: %d bytes\n", buffer_size);
+ }
+
+ if (is_directory(input_path)) {
+ create_directory(output_path);
+ process_directory(mode, keyword, input_path, output_path, mixed_alphabet, punctuation_mapping, disable_base64, enable_verbosity, buffer_size);
+ } else {
+ process_file(mode, keyword, input_path, output_path, mixed_alphabet, punctuation_mapping, disable_base64, enable_verbosity, buffer_size);
+ }
+
+ return 0;
+}