From ae0afcfffd4bf592a35188353b4b25120757a2ca Mon Sep 17 00:00:00 2001 From: Laan Tungir Date: Sun, 10 Aug 2025 10:16:33 -0400 Subject: [PATCH] Version v0.2.14 - small fix --- .gitignore | 1 + otp.c | 182 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 122 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index 6f01cd6..ca2707a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +otp pads/ Gemini.md diff --git a/otp.c b/otp.c index a0cc5da..ed1a5b5 100644 --- a/otp.c +++ b/otp.c @@ -50,8 +50,8 @@ int command_line_mode(int argc, char* argv[]); // Core functions int generate_pad(uint64_t size_bytes, int show_progress); int generate_pad_with_entropy(uint64_t size_bytes, int show_progress, int use_keyboard_entropy); -int encrypt_text(const char* pad_identifier); -int decrypt_text(const char* pad_identifier); +int encrypt_text(const char* pad_identifier, const char* input_text); +int decrypt_text(const char* pad_identifier, const char* encrypted_message); // Keyboard entropy functions int setup_raw_terminal(struct termios* original_termios); @@ -161,18 +161,22 @@ int command_line_mode(int argc, char* argv[]) { return generate_pad_with_entropy(size, 1, 0); // No keyboard entropy for command line } else if (strcmp(argv[1], "encrypt") == 0) { - if (argc != 3) { - printf("Usage: %s encrypt \n", argv[0]); + if (argc < 3 || argc > 4) { + printf("Usage: %s encrypt [text_to_encrypt]\n", argv[0]); return 1; } - return encrypt_text(argv[2]); + // Pass text if provided, otherwise NULL for interactive mode + const char* text = (argc == 4) ? argv[3] : NULL; + return encrypt_text(argv[2], text); } else if (strcmp(argv[1], "decrypt") == 0) { - if (argc != 3) { - printf("Usage: %s decrypt \n", argv[0]); + if (argc < 3 || argc > 4) { + printf("Usage: %s decrypt [encrypted_message]\n", argv[0]); return 1; } - return decrypt_text(argv[2]); + // Pass message if provided, otherwise NULL for interactive mode + const char* message = (argc == 4) ? argv[3] : NULL; + return decrypt_text(argv[2], message); } else if (strcmp(argv[1], "list") == 0) { return list_available_pads(); @@ -250,12 +254,12 @@ int handle_encrypt_menu(void) { } input[strcspn(input, "\n")] = 0; - return encrypt_text(input); + return encrypt_text(input, NULL); // NULL for interactive mode } int handle_decrypt_menu(void) { printf("\n=== Decrypt Message ===\n"); - return decrypt_text(NULL); // No pad selection needed - chksum comes from message + return decrypt_text(NULL, NULL); // No pad selection needed - chksum comes from message } uint64_t parse_size_string(const char* size_str) { @@ -797,13 +801,13 @@ int generate_pad_with_entropy(uint64_t size_bytes, int display_progress, int use return 0; } -int encrypt_text(const char* pad_identifier) { +int encrypt_text(const char* pad_identifier, const char* input_text) { char* pad_chksum = find_pad_by_prefix(pad_identifier); if (!pad_chksum) { return 1; } - char input_text[MAX_INPUT_SIZE]; + char text_buffer[MAX_INPUT_SIZE]; char chksum_hex[MAX_HASH_LENGTH]; uint64_t current_offset; @@ -841,23 +845,30 @@ int encrypt_text(const char* pad_identifier) { return 1; } - // Get input text from user - printf("Enter text to encrypt: "); - fflush(stdout); - - if (fgets(input_text, sizeof(input_text), stdin) == NULL) { - printf("Error: Failed to read input\n"); - free(pad_chksum); - return 1; - } - - // Remove newline if present - size_t input_len = strlen(input_text); - if (input_len > 0 && input_text[input_len - 1] == '\n') { - input_text[input_len - 1] = '\0'; - input_len--; + // Get input text - either from parameter or user input + if (input_text != NULL) { + // Use provided text + strncpy(text_buffer, input_text, sizeof(text_buffer) - 1); + text_buffer[sizeof(text_buffer) - 1] = '\0'; + } else { + // Get input text from user (interactive mode) + printf("Enter text to encrypt: "); + fflush(stdout); + + if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) { + printf("Error: Failed to read input\n"); + free(pad_chksum); + return 1; + } + + // Remove newline if present + size_t len = strlen(text_buffer); + if (len > 0 && text_buffer[len - 1] == '\n') { + text_buffer[len - 1] = '\0'; + } } + size_t input_len = strlen(text_buffer); if (input_len == 0) { printf("Error: No input provided\n"); free(pad_chksum); @@ -908,7 +919,7 @@ int encrypt_text(const char* pad_identifier) { // XOR encrypt the input unsigned char* ciphertext = malloc(input_len); for (size_t i = 0; i < input_len; i++) { - ciphertext[i] = input_text[i] ^ pad_data[i]; + ciphertext[i] = text_buffer[i] ^ pad_data[i]; } // Encode as base64 @@ -943,7 +954,7 @@ int encrypt_text(const char* pad_identifier) { return 0; } -int decrypt_text(const char* pad_identifier) { +int decrypt_text(const char* pad_identifier, const char* encrypted_message) { // For command line mode, pad_identifier is ignored - we'll get the chksum from the message (void)pad_identifier; // Suppress unused parameter warning @@ -954,36 +965,80 @@ int decrypt_text(const char* pad_identifier) { char base64_data[MAX_INPUT_SIZE * 2] = {0}; int in_data_section = 0; - printf("Enter encrypted message (paste the full ASCII armor block):\n"); - - // Read the ASCII armor format - int found_begin = 0; - while (fgets(line, sizeof(line), stdin)) { - line[strcspn(line, "\n")] = 0; + if (encrypted_message != NULL) { + // Parse provided encrypted message + char *message_copy = strdup(encrypted_message); + char *line_ptr = strtok(message_copy, "\n"); - if (strcmp(line, "-----BEGIN OTP MESSAGE-----") == 0) { - found_begin = 1; - continue; + int found_begin = 0; + while (line_ptr != NULL) { + if (strcmp(line_ptr, "-----BEGIN OTP MESSAGE-----") == 0) { + found_begin = 1; + } + else if (strcmp(line_ptr, "-----END OTP MESSAGE-----") == 0) { + break; + } + else if (found_begin) { + if (strncmp(line_ptr, "Pad-ChkSum: ", 12) == 0) { + strncpy(stored_chksum, line_ptr + 12, 64); + stored_chksum[64] = '\0'; + } + else if (strncmp(line_ptr, "Pad-Offset: ", 12) == 0) { + pad_offset = strtoull(line_ptr + 12, NULL, 10); + } + else if (strlen(line_ptr) == 0) { + in_data_section = 1; + } + else if (in_data_section) { + strncat(base64_data, line_ptr, sizeof(base64_data) - strlen(base64_data) - 1); + } + } + line_ptr = strtok(NULL, "\n"); + } + free(message_copy); + + if (!found_begin) { + printf("Error: Invalid message format - missing BEGIN header\n"); + return 1; + } + } else { + // Interactive mode - read from stdin + printf("Enter encrypted message (paste the full ASCII armor block):\n"); + + // Read the ASCII armor format + int found_begin = 0; + while (fgets(line, sizeof(line), stdin)) { + line[strcspn(line, "\n")] = 0; + + if (strcmp(line, "-----BEGIN OTP MESSAGE-----") == 0) { + found_begin = 1; + continue; + } + + if (strcmp(line, "-----END OTP MESSAGE-----") == 0) { + break; + } + + if (!found_begin) continue; + + if (strncmp(line, "Pad-ChkSum: ", 12) == 0) { + strncpy(stored_chksum, line + 12, 64); + stored_chksum[64] = '\0'; + } + else if (strncmp(line, "Pad-Offset: ", 12) == 0) { + pad_offset = strtoull(line + 12, NULL, 10); + } + else if (strlen(line) == 0) { + in_data_section = 1; + } + else if (in_data_section) { + strncat(base64_data, line, sizeof(base64_data) - strlen(base64_data) - 1); + } } - if (strcmp(line, "-----END OTP MESSAGE-----") == 0) { - break; - } - - if (!found_begin) continue; - - if (strncmp(line, "Pad-ChkSum: ", 12) == 0) { - strncpy(stored_chksum, line + 12, 64); - stored_chksum[64] = '\0'; - } - else if (strncmp(line, "Pad-Offset: ", 12) == 0) { - pad_offset = strtoull(line + 12, NULL, 10); - } - else if (strlen(line) == 0) { - in_data_section = 1; - } - else if (in_data_section) { - strncat(base64_data, line, sizeof(base64_data) - strlen(base64_data) - 1); + if (!found_begin) { + printf("Error: Invalid message format - missing BEGIN header\n"); + return 1; } } @@ -1345,11 +1400,16 @@ void print_usage(const char* program_name) { printf("OTP Cipher - One Time Pad Implementation %s\n", get_version()); printf("%s\n", get_build_info()); printf("Usage:\n"); - printf(" %s - Interactive mode\n", program_name); - printf(" %s generate - Generate new pad\n", program_name); - printf(" %s encrypt - Encrypt text\n", program_name); - printf(" %s decrypt - Decrypt message\n", program_name); - printf(" %s list - List available pads\n", program_name); + printf(" %s - Interactive mode\n", program_name); + printf(" %s generate - Generate new pad\n", program_name); + printf(" %s encrypt [text] - Encrypt text\n", program_name); + printf(" %s decrypt [message] - Decrypt message\n", program_name); + printf(" %s list - List available pads\n", program_name); + printf("\nExamples:\n"); + printf(" %s encrypt 1a2b3c \"Hello world\" - Encrypt inline text\n", program_name); + printf(" %s encrypt 1a2b3c - Encrypt interactively\n", program_name); + printf(" %s decrypt 1a2b3c \"-----BEGIN OTP...\" - Decrypt inline message\n", program_name); + printf(" %s decrypt 1a2b3c - Decrypt interactively\n", program_name); printf("\nSize examples: 1GB, 5TB, 512MB, 2048 (bytes)\n"); printf("Pad selection: Full chksum, prefix, or number from list\n"); }