Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82533d96e4 | |||
| 5b619384a1 | |||
| 12b9884572 | |||
| 83b60b5cc2 | |||
| 2d6546ab83 | |||
| c255185084 | |||
| 24800d69d5 | |||
| 7e50727163 | |||
| f118c23c60 | |||
| b149175f24 | |||
| 206e8042d8 | |||
| 2a5249d93c | |||
| 0e02eaee53 | |||
| e32eb8b2b1 | |||
| 0aecae0c5e |
@@ -2,3 +2,6 @@
|
|||||||
When building, use build.sh, not make.
|
When building, use build.sh, not make.
|
||||||
|
|
||||||
Use it as follows: build.sh -m "useful comment on changes being made"
|
Use it as follows: build.sh -m "useful comment on changes being made"
|
||||||
|
|
||||||
|
When making TUI menus, try to use the first leter of the command and the key to press to execute that command. For example, if the command is "Open file" try to use a keypress of "o" upper or lower case to signal to open the file. Use this instead of number keyed menus when possible. In the command, the letter should be underlined that signifies the command.
|
||||||
|
|
||||||
|
|||||||
1
decrypted.bin
Normal file
1
decrypted.bin
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, this is a test file for encryption!
|
||||||
BIN
files/output.otp
Normal file
BIN
files/output.otp
Normal file
Binary file not shown.
1
files/test_decrypt.txt
Normal file
1
files/test_decrypt.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Test file content for decryption
|
||||||
BIN
files/test_decrypt.txt.otp
Normal file
BIN
files/test_decrypt.txt.otp
Normal file
Binary file not shown.
1
files/test_file.txt
Normal file
1
files/test_file.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, this is a test file for encryption!
|
||||||
7
files/test_file.txt.otp.asc
Normal file
7
files/test_file.txt.otp.asc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
-----BEGIN OTP MESSAGE-----
|
||||||
|
Version: v0.2.29
|
||||||
|
Pad-ChkSum: d0d4a489354348b08d8c7b324814d8c50010042e9da47f2c973f32a16a09101b
|
||||||
|
Pad-Offset: 57
|
||||||
|
|
||||||
|
05S8GfS0tFfczNMUz0xrieFGoPSREM4uo5QhFGoBCcOzjfTXTDMt3hRtAQ==
|
||||||
|
-----END OTP MESSAGE-----
|
||||||
1
files/test_input.txt
Normal file
1
files/test_input.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This is a test file for encryption.
|
||||||
BIN
files/toc.txt.otp
Normal file
BIN
files/toc.txt.otp
Normal file
Binary file not shown.
774
otp.c
774
otp.c
@@ -40,6 +40,7 @@ static const int base64_decode_table[256] = {
|
|||||||
#define MAX_HASH_LENGTH 65
|
#define MAX_HASH_LENGTH 65
|
||||||
#define PROGRESS_UPDATE_INTERVAL (64 * 1024 * 1024) // 64MB intervals
|
#define PROGRESS_UPDATE_INTERVAL (64 * 1024 * 1024) // 64MB intervals
|
||||||
#define PADS_DIR "pads"
|
#define PADS_DIR "pads"
|
||||||
|
#define FILES_DIR "files"
|
||||||
#define MAX_ENTROPY_BUFFER 32768 // 32KB entropy buffer
|
#define MAX_ENTROPY_BUFFER 32768 // 32KB entropy buffer
|
||||||
|
|
||||||
// Function prototypes
|
// Function prototypes
|
||||||
@@ -47,6 +48,12 @@ int main(int argc, char* argv[]);
|
|||||||
int interactive_mode(void);
|
int interactive_mode(void);
|
||||||
int command_line_mode(int argc, char* argv[]);
|
int command_line_mode(int argc, char* argv[]);
|
||||||
|
|
||||||
|
// Editor and file manager functions
|
||||||
|
char* get_preferred_editor(void);
|
||||||
|
char* get_preferred_file_manager(void);
|
||||||
|
int launch_text_editor(const char* initial_content, char* result_buffer, size_t buffer_size);
|
||||||
|
int launch_file_manager(const char* start_directory, char* selected_file, size_t buffer_size);
|
||||||
|
|
||||||
// Core functions
|
// Core functions
|
||||||
int generate_pad(uint64_t size_bytes, int show_progress);
|
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 generate_pad_with_entropy(uint64_t size_bytes, int show_progress, int use_keyboard_entropy);
|
||||||
@@ -66,7 +73,10 @@ void simple_entropy_mix(unsigned char* urandom_buffer, size_t buffer_size,
|
|||||||
|
|
||||||
// Directory management
|
// Directory management
|
||||||
int ensure_pads_directory(void);
|
int ensure_pads_directory(void);
|
||||||
|
int ensure_files_directory(void);
|
||||||
void get_pad_path(const char* chksum, char* pad_path, char* state_path);
|
void get_pad_path(const char* chksum, char* pad_path, char* state_path);
|
||||||
|
const char* get_files_directory(void);
|
||||||
|
void get_default_file_path(const char* filename, char* result_path, size_t result_size);
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
uint64_t parse_size_string(const char* size_str);
|
uint64_t parse_size_string(const char* size_str);
|
||||||
@@ -89,6 +99,12 @@ void show_main_menu(void);
|
|||||||
int handle_generate_menu(void);
|
int handle_generate_menu(void);
|
||||||
int handle_encrypt_menu(void);
|
int handle_encrypt_menu(void);
|
||||||
int handle_decrypt_menu(void);
|
int handle_decrypt_menu(void);
|
||||||
|
int handle_text_encrypt(void);
|
||||||
|
int handle_file_encrypt(void);
|
||||||
|
int handle_smart_decrypt(void);
|
||||||
|
|
||||||
|
// Enhanced input functions
|
||||||
|
int get_filename_with_default(const char* prompt, const char* default_path, char* result, size_t result_size);
|
||||||
|
|
||||||
void print_usage(const char* program_name);
|
void print_usage(const char* program_name);
|
||||||
|
|
||||||
@@ -101,7 +117,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int interactive_mode(void) {
|
int interactive_mode(void) {
|
||||||
printf("=== OTP Cipher %s ===\n\n", get_version());
|
printf("\n\n\n\n=== OTP Cipher %s ===\n\n", get_version());
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
show_main_menu();
|
show_main_menu();
|
||||||
@@ -110,14 +126,17 @@ int interactive_mode(void) {
|
|||||||
char choice = toupper(input[0]);
|
char choice = toupper(input[0]);
|
||||||
|
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
case 'G':
|
case 'T':
|
||||||
handle_generate_menu();
|
handle_text_encrypt();
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'F':
|
||||||
handle_encrypt_menu();
|
handle_file_encrypt();
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
handle_decrypt_menu();
|
handle_smart_decrypt();
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
handle_generate_menu();
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
list_available_pads();
|
list_available_pads();
|
||||||
@@ -136,10 +155,11 @@ int interactive_mode(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'X':
|
case 'X':
|
||||||
|
case 'Q':
|
||||||
printf("Goodbye!\n");
|
printf("Goodbye!\n");
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
printf("Invalid option. Please select G, E, D, L, S, or X.\n");
|
printf("Invalid option. Please select T, F, D, G, L, S, or X.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -255,10 +275,11 @@ int command_line_mode(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void show_main_menu(void) {
|
void show_main_menu(void) {
|
||||||
printf("=== Main Menu ===\n");
|
printf("======================== Main Menu ========================\n");
|
||||||
|
printf("\033[4mT\033[0mext encrypt\n");
|
||||||
|
printf("\033[4mF\033[0mile encrypt\n");
|
||||||
|
printf("\033[4mD\033[0mecrypt\n");
|
||||||
printf("\033[4mG\033[0menerate new pad\n");
|
printf("\033[4mG\033[0menerate new pad\n");
|
||||||
printf("\033[4mE\033[0mncrypt data (text/file)\n");
|
|
||||||
printf("\033[4mD\033[0mecrypt data (text/file)\n");
|
|
||||||
printf("\033[4mL\033[0mist available pads\n");
|
printf("\033[4mL\033[0mist available pads\n");
|
||||||
printf("\033[4mS\033[0mhow pad information\n");
|
printf("\033[4mS\033[0mhow pad information\n");
|
||||||
printf("E\033[4mx\033[0mit\n");
|
printf("E\033[4mx\033[0mit\n");
|
||||||
@@ -329,25 +350,92 @@ int handle_encrypt_menu(void) {
|
|||||||
|
|
||||||
if (choice == 1) {
|
if (choice == 1) {
|
||||||
// Text encryption
|
// Text encryption
|
||||||
printf("\nEnter pad selection (number, chksum, or prefix): ");
|
printf("\nPad selection options:\n");
|
||||||
char input[MAX_HASH_LENGTH];
|
printf("1. Select from numbered list\n");
|
||||||
if (!fgets(input, sizeof(input), stdin)) {
|
printf("2. Enter checksum/prefix manually\n");
|
||||||
|
printf("3. Browse pad files\n");
|
||||||
|
printf("Enter choice (1-3): ");
|
||||||
|
|
||||||
|
char pad_choice[10];
|
||||||
|
if (!fgets(pad_choice, sizeof(pad_choice), stdin)) {
|
||||||
printf("Error: Failed to read input\n");
|
printf("Error: Failed to read input\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[strcspn(input, "\n")] = 0;
|
char input[MAX_HASH_LENGTH];
|
||||||
|
if (atoi(pad_choice) == 3) {
|
||||||
|
// Use file manager to browse pads directory
|
||||||
|
char selected_pad[512];
|
||||||
|
if (launch_file_manager("pads", selected_pad, sizeof(selected_pad)) == 0) {
|
||||||
|
// Extract checksum from selected .pad file
|
||||||
|
char* filename = strrchr(selected_pad, '/');
|
||||||
|
if (!filename) filename = selected_pad;
|
||||||
|
else filename++; // Skip the '/'
|
||||||
|
|
||||||
|
// Remove .pad extension to get checksum
|
||||||
|
if (strlen(filename) == 68 && strstr(filename, ".pad")) {
|
||||||
|
strncpy(input, filename, 64);
|
||||||
|
input[64] = '\0';
|
||||||
|
} else {
|
||||||
|
printf("Invalid pad file selected.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Falling back to manual pad selection.\n");
|
||||||
|
printf("Enter pad selection (number, chksum, or prefix): ");
|
||||||
|
if (!fgets(input, sizeof(input), stdin)) {
|
||||||
|
printf("Error: Failed to read input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
input[strcspn(input, "\n")] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Manual pad selection
|
||||||
|
printf("Enter pad selection (number, chksum, or prefix): ");
|
||||||
|
if (!fgets(input, sizeof(input), stdin)) {
|
||||||
|
printf("Error: Failed to read input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
input[strcspn(input, "\n")] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return encrypt_text(input, NULL); // NULL for interactive mode
|
return encrypt_text(input, NULL); // NULL for interactive mode
|
||||||
}
|
}
|
||||||
else if (choice == 2) {
|
else if (choice == 2) {
|
||||||
// File encryption
|
// File encryption
|
||||||
printf("\nEnter input file path: ");
|
printf("\nFile selection options:\n");
|
||||||
|
printf("1. Type file path directly\n");
|
||||||
|
printf("2. Use file manager\n");
|
||||||
|
printf("Enter choice (1-2): ");
|
||||||
|
|
||||||
|
char file_choice[10];
|
||||||
char input_file[512];
|
char input_file[512];
|
||||||
if (!fgets(input_file, sizeof(input_file), stdin)) {
|
|
||||||
|
if (!fgets(file_choice, sizeof(file_choice), stdin)) {
|
||||||
printf("Error: Failed to read input\n");
|
printf("Error: Failed to read input\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
input_file[strcspn(input_file, "\n")] = 0;
|
|
||||||
|
if (atoi(file_choice) == 2) {
|
||||||
|
// Use file manager
|
||||||
|
if (launch_file_manager(".", input_file, sizeof(input_file)) != 0) {
|
||||||
|
printf("Falling back to manual file path entry.\n");
|
||||||
|
printf("Enter input file path: ");
|
||||||
|
if (!fgets(input_file, sizeof(input_file), stdin)) {
|
||||||
|
printf("Error: Failed to read input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
input_file[strcspn(input_file, "\n")] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Direct file path input
|
||||||
|
printf("Enter input file path: ");
|
||||||
|
if (!fgets(input_file, sizeof(input_file), stdin)) {
|
||||||
|
printf("Error: Failed to read input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
input_file[strcspn(input_file, "\n")] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
if (access(input_file, R_OK) != 0) {
|
if (access(input_file, R_OK) != 0) {
|
||||||
@@ -377,16 +465,27 @@ int handle_encrypt_menu(void) {
|
|||||||
|
|
||||||
int ascii_armor = (atoi(format_input) == 2) ? 1 : 0;
|
int ascii_armor = (atoi(format_input) == 2) ? 1 : 0;
|
||||||
|
|
||||||
// Ask for custom output filename (optional)
|
// Generate default output filename with files directory and use enhanced input function
|
||||||
printf("\nEnter output filename (or press Enter for default): ");
|
char default_output[1024]; // Increased size to prevent truncation warnings
|
||||||
|
char temp_default[1024];
|
||||||
|
|
||||||
|
// Generate base filename with appropriate extension
|
||||||
|
if (ascii_armor) {
|
||||||
|
snprintf(temp_default, sizeof(temp_default), "%s.otp.asc", input_file);
|
||||||
|
} else {
|
||||||
|
snprintf(temp_default, sizeof(temp_default), "%s.otp", input_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply files directory default path
|
||||||
|
get_default_file_path(temp_default, default_output, sizeof(default_output));
|
||||||
|
|
||||||
char output_file[512];
|
char output_file[512];
|
||||||
if (!fgets(output_file, sizeof(output_file), stdin)) {
|
if (get_filename_with_default("Output filename:", default_output, output_file, sizeof(output_file)) != 0) {
|
||||||
printf("Error: Failed to read input\n");
|
printf("Error: Failed to read input\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
output_file[strcspn(output_file, "\n")] = 0;
|
|
||||||
|
|
||||||
const char* output_filename = (strlen(output_file) > 0) ? output_file : NULL;
|
const char* output_filename = output_file;
|
||||||
|
|
||||||
return encrypt_file(pad_input, input_file, output_filename, ascii_armor);
|
return encrypt_file(pad_input, input_file, output_filename, ascii_armor);
|
||||||
}
|
}
|
||||||
@@ -433,16 +532,36 @@ int handle_decrypt_menu(void) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask for custom output filename (optional)
|
// Generate smart default output filename with files directory and use enhanced input function
|
||||||
printf("\nEnter output filename (or press Enter for default): ");
|
char temp_default[512];
|
||||||
|
char default_output[512];
|
||||||
|
strncpy(temp_default, input_file, sizeof(temp_default) - 1);
|
||||||
|
temp_default[sizeof(temp_default) - 1] = '\0';
|
||||||
|
|
||||||
|
// Remove common encrypted extensions to get a better default
|
||||||
|
if (strstr(temp_default, ".otp.asc")) {
|
||||||
|
// Replace .otp.asc with original extension or no extension
|
||||||
|
char* ext_pos = strstr(temp_default, ".otp.asc");
|
||||||
|
*ext_pos = '\0';
|
||||||
|
} else if (strstr(temp_default, ".otp")) {
|
||||||
|
// Replace .otp with original extension or no extension
|
||||||
|
char* ext_pos = strstr(temp_default, ".otp");
|
||||||
|
*ext_pos = '\0';
|
||||||
|
} else {
|
||||||
|
// No recognized encrypted extension, add .decrypted suffix
|
||||||
|
strncat(temp_default, ".decrypted", sizeof(temp_default) - strlen(temp_default) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply files directory default path
|
||||||
|
get_default_file_path(temp_default, default_output, sizeof(default_output));
|
||||||
|
|
||||||
char output_file[512];
|
char output_file[512];
|
||||||
if (!fgets(output_file, sizeof(output_file), stdin)) {
|
if (get_filename_with_default("Output filename:", default_output, output_file, sizeof(output_file)) != 0) {
|
||||||
printf("Error: Failed to read input\n");
|
printf("Error: Failed to read input\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
output_file[strcspn(output_file, "\n")] = 0;
|
|
||||||
|
|
||||||
const char* output_filename = (strlen(output_file) > 0) ? output_file : NULL;
|
const char* output_filename = output_file;
|
||||||
|
|
||||||
return decrypt_file(input_file, output_filename);
|
return decrypt_file(input_file, output_filename);
|
||||||
}
|
}
|
||||||
@@ -1076,19 +1195,53 @@ int encrypt_text(const char* pad_identifier, const char* input_text) {
|
|||||||
text_buffer[sizeof(text_buffer) - 1] = '\0';
|
text_buffer[sizeof(text_buffer) - 1] = '\0';
|
||||||
} else {
|
} else {
|
||||||
// Get input text from user (interactive mode)
|
// Get input text from user (interactive mode)
|
||||||
printf("Enter text to encrypt: ");
|
printf("\nText input options:\n");
|
||||||
fflush(stdout);
|
printf("1. Type text directly\n");
|
||||||
|
printf("2. Use text editor\n");
|
||||||
|
printf("Enter choice (1-2): ");
|
||||||
|
|
||||||
if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) {
|
char input_choice[10];
|
||||||
|
if (!fgets(input_choice, sizeof(input_choice), stdin)) {
|
||||||
printf("Error: Failed to read input\n");
|
printf("Error: Failed to read input\n");
|
||||||
free(pad_chksum);
|
free(pad_chksum);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove newline if present
|
if (atoi(input_choice) == 2) {
|
||||||
size_t len = strlen(text_buffer);
|
// Use text editor
|
||||||
if (len > 0 && text_buffer[len - 1] == '\n') {
|
if (launch_text_editor(NULL, text_buffer, sizeof(text_buffer)) != 0) {
|
||||||
text_buffer[len - 1] = '\0';
|
printf("Falling back to direct text input.\n");
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Direct text input
|
||||||
|
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';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2090,6 +2243,38 @@ int ensure_pads_directory(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ensure_files_directory(void) {
|
||||||
|
struct stat st = {0};
|
||||||
|
if (stat(FILES_DIR, &st) == -1) {
|
||||||
|
if (mkdir(FILES_DIR, 0755) != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* get_files_directory(void) {
|
||||||
|
struct stat st = {0};
|
||||||
|
if (stat(FILES_DIR, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||||
|
return FILES_DIR;
|
||||||
|
}
|
||||||
|
return "."; // Fall back to current directory
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_default_file_path(const char* filename, char* result_path, size_t result_size) {
|
||||||
|
const char* files_dir = get_files_directory();
|
||||||
|
|
||||||
|
// If filename already has a path (contains '/'), use it as-is
|
||||||
|
if (strchr(filename, '/') != NULL) {
|
||||||
|
strncpy(result_path, filename, result_size - 1);
|
||||||
|
result_path[result_size - 1] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, prepend the files directory
|
||||||
|
snprintf(result_path, result_size, "%s/%s", files_dir, filename);
|
||||||
|
}
|
||||||
|
|
||||||
void get_pad_path(const char* chksum, char* pad_path, char* state_path) {
|
void get_pad_path(const char* chksum, char* pad_path, char* state_path) {
|
||||||
snprintf(pad_path, MAX_HASH_LENGTH + 20, "%s/%s.pad", PADS_DIR, chksum);
|
snprintf(pad_path, MAX_HASH_LENGTH + 20, "%s/%s.pad", PADS_DIR, chksum);
|
||||||
snprintf(state_path, MAX_HASH_LENGTH + 20, "%s/%s.state", PADS_DIR, chksum);
|
snprintf(state_path, MAX_HASH_LENGTH + 20, "%s/%s.state", PADS_DIR, chksum);
|
||||||
@@ -2182,6 +2367,527 @@ void simple_entropy_mix(unsigned char* urandom_buffer, size_t buffer_size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enhanced input function with editable pre-filled text
|
||||||
|
int get_filename_with_default(const char* prompt, const char* default_path, char* result, size_t result_size) {
|
||||||
|
// Find the last directory separator
|
||||||
|
char* last_slash = strrchr(default_path, '/');
|
||||||
|
char directory[1024] = "";
|
||||||
|
char filename[512] = "";
|
||||||
|
|
||||||
|
if (last_slash) {
|
||||||
|
// Extract directory path
|
||||||
|
size_t dir_len = last_slash - default_path + 1; // Include the trailing slash
|
||||||
|
if (dir_len < sizeof(directory)) {
|
||||||
|
strncpy(directory, default_path, dir_len);
|
||||||
|
directory[dir_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract filename
|
||||||
|
strncpy(filename, last_slash + 1, sizeof(filename) - 1);
|
||||||
|
filename[sizeof(filename) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
// No directory separator, treat as filename only
|
||||||
|
strncpy(filename, default_path, sizeof(filename) - 1);
|
||||||
|
filename[sizeof(filename) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup terminal for raw input
|
||||||
|
struct termios orig_termios;
|
||||||
|
if (tcgetattr(STDIN_FILENO, &orig_termios) != 0) {
|
||||||
|
// Fallback to simple input if terminal control fails
|
||||||
|
printf("\n%s\n%s: ", prompt, directory);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
char input_buffer[512];
|
||||||
|
if (!fgets(input_buffer, sizeof(input_buffer), stdin)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
input_buffer[strcspn(input_buffer, "\n")] = 0;
|
||||||
|
|
||||||
|
if (strlen(input_buffer) == 0) {
|
||||||
|
strncpy(result, default_path, result_size - 1);
|
||||||
|
} else {
|
||||||
|
if (strlen(directory) > 0) {
|
||||||
|
snprintf(result, result_size, "%s%s", directory, input_buffer);
|
||||||
|
} else {
|
||||||
|
strncpy(result, input_buffer, result_size - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[result_size - 1] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up raw terminal mode
|
||||||
|
struct termios raw_termios = orig_termios;
|
||||||
|
raw_termios.c_lflag &= ~(ECHO | ICANON);
|
||||||
|
raw_termios.c_cc[VMIN] = 1;
|
||||||
|
raw_termios.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
|
if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_termios) != 0) {
|
||||||
|
// Fallback if terminal setup fails
|
||||||
|
printf("\n%s\n%s: ", prompt, directory);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
char input_buffer[512];
|
||||||
|
if (!fgets(input_buffer, sizeof(input_buffer), stdin)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
input_buffer[strcspn(input_buffer, "\n")] = 0;
|
||||||
|
|
||||||
|
if (strlen(input_buffer) == 0) {
|
||||||
|
strncpy(result, default_path, result_size - 1);
|
||||||
|
} else {
|
||||||
|
if (strlen(directory) > 0) {
|
||||||
|
snprintf(result, result_size, "%s%s", directory, input_buffer);
|
||||||
|
} else {
|
||||||
|
strncpy(result, input_buffer, result_size - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[result_size - 1] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display prompt and directory
|
||||||
|
printf("\n%s\n%s", prompt, directory);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
// Initialize editing buffer with default filename
|
||||||
|
char edit_buffer[512];
|
||||||
|
strncpy(edit_buffer, filename, sizeof(edit_buffer) - 1);
|
||||||
|
edit_buffer[sizeof(edit_buffer) - 1] = '\0';
|
||||||
|
int cursor_pos = strlen(edit_buffer);
|
||||||
|
int buffer_len = cursor_pos;
|
||||||
|
|
||||||
|
// Display initial filename
|
||||||
|
printf("%s", edit_buffer);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
// Main editing loop
|
||||||
|
int c;
|
||||||
|
while ((c = getchar()) != EOF) {
|
||||||
|
if (c == '\n' || c == '\r') {
|
||||||
|
// Enter key - accept input
|
||||||
|
break;
|
||||||
|
} else if (c == 127 || c == 8) {
|
||||||
|
// Backspace/Delete
|
||||||
|
if (cursor_pos > 0) {
|
||||||
|
// Move everything after cursor one position left
|
||||||
|
memmove(&edit_buffer[cursor_pos - 1], &edit_buffer[cursor_pos], buffer_len - cursor_pos + 1);
|
||||||
|
cursor_pos--;
|
||||||
|
buffer_len--;
|
||||||
|
|
||||||
|
// Redraw line: move cursor to start of filename area, clear to end, redraw buffer
|
||||||
|
printf("\r%s\033[K%s", directory, edit_buffer);
|
||||||
|
|
||||||
|
// Position cursor correctly
|
||||||
|
if (cursor_pos < buffer_len) {
|
||||||
|
printf("\033[%dD", buffer_len - cursor_pos);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
} else if (c == 27) {
|
||||||
|
// Escape sequence (arrow keys, etc.)
|
||||||
|
int c1 = getchar();
|
||||||
|
int c2 = getchar();
|
||||||
|
if (c1 == '[') {
|
||||||
|
if (c2 == 'C' && cursor_pos < buffer_len) {
|
||||||
|
// Right arrow
|
||||||
|
cursor_pos++;
|
||||||
|
printf("\033[1C");
|
||||||
|
fflush(stdout);
|
||||||
|
} else if (c2 == 'D' && cursor_pos > 0) {
|
||||||
|
// Left arrow
|
||||||
|
cursor_pos--;
|
||||||
|
printf("\033[1D");
|
||||||
|
fflush(stdout);
|
||||||
|
} else if (c2 == 'H') {
|
||||||
|
// Home key
|
||||||
|
printf("\033[%dD", cursor_pos);
|
||||||
|
cursor_pos = 0;
|
||||||
|
fflush(stdout);
|
||||||
|
} else if (c2 == 'F') {
|
||||||
|
// End key
|
||||||
|
printf("\033[%dC", buffer_len - cursor_pos);
|
||||||
|
cursor_pos = buffer_len;
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (c >= 32 && c <= 126) {
|
||||||
|
// Printable character
|
||||||
|
if (buffer_len < (int)sizeof(edit_buffer) - 1) {
|
||||||
|
// Move everything after cursor one position right
|
||||||
|
memmove(&edit_buffer[cursor_pos + 1], &edit_buffer[cursor_pos], buffer_len - cursor_pos + 1);
|
||||||
|
edit_buffer[cursor_pos] = c;
|
||||||
|
cursor_pos++;
|
||||||
|
buffer_len++;
|
||||||
|
|
||||||
|
// Redraw from cursor position
|
||||||
|
printf("%c", c);
|
||||||
|
if (cursor_pos < buffer_len) {
|
||||||
|
// Print remaining characters and move cursor back
|
||||||
|
printf("%s\033[%dD", &edit_buffer[cursor_pos], buffer_len - cursor_pos);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ignore other control characters
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore terminal
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// Construct final result
|
||||||
|
if (buffer_len == 0) {
|
||||||
|
// Empty input, use default
|
||||||
|
strncpy(result, default_path, result_size - 1);
|
||||||
|
} else {
|
||||||
|
// Combine directory with edited filename
|
||||||
|
edit_buffer[buffer_len] = '\0';
|
||||||
|
if (strlen(directory) > 0) {
|
||||||
|
snprintf(result, result_size, "%s%s", directory, edit_buffer);
|
||||||
|
} else {
|
||||||
|
strncpy(result, edit_buffer, result_size - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[result_size - 1] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Editor and file manager implementations
|
||||||
|
|
||||||
|
char* get_preferred_editor(void) {
|
||||||
|
// Check EDITOR environment variable first
|
||||||
|
char* editor = getenv("EDITOR");
|
||||||
|
if (editor && strlen(editor) > 0) {
|
||||||
|
// Verify the editor exists
|
||||||
|
char command[512];
|
||||||
|
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", editor);
|
||||||
|
if (system(command) == 0) {
|
||||||
|
return strdup(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check VISUAL environment variable
|
||||||
|
editor = getenv("VISUAL");
|
||||||
|
if (editor && strlen(editor) > 0) {
|
||||||
|
char command[512];
|
||||||
|
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", editor);
|
||||||
|
if (system(command) == 0) {
|
||||||
|
return strdup(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try common editors in order of preference
|
||||||
|
const char* common_editors[] = {"vim", "vi", "nano", "emacs", "gedit", NULL};
|
||||||
|
for (int i = 0; common_editors[i] != NULL; i++) {
|
||||||
|
char command[512];
|
||||||
|
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", common_editors[i]);
|
||||||
|
if (system(command) == 0) {
|
||||||
|
return strdup(common_editors[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // No editor found
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_preferred_file_manager(void) {
|
||||||
|
// Try file managers in order of preference
|
||||||
|
const char* file_managers[] = {"ranger", "fzf", "nnn", "lf", NULL};
|
||||||
|
|
||||||
|
for (int i = 0; file_managers[i] != NULL; i++) {
|
||||||
|
char command[512];
|
||||||
|
snprintf(command, sizeof(command), "which %s >/dev/null 2>&1", file_managers[i]);
|
||||||
|
if (system(command) == 0) {
|
||||||
|
return strdup(file_managers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // No file manager found
|
||||||
|
}
|
||||||
|
|
||||||
|
int launch_text_editor(const char* initial_content, char* result_buffer, size_t buffer_size) {
|
||||||
|
char* editor = get_preferred_editor();
|
||||||
|
if (!editor) {
|
||||||
|
printf("Error: No text editor found. Set EDITOR environment variable or install vim/nano.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create temporary file
|
||||||
|
char temp_filename[64];
|
||||||
|
snprintf(temp_filename, sizeof(temp_filename), "/tmp/otp_edit_%ld.tmp", time(NULL));
|
||||||
|
|
||||||
|
// Write initial content to temp file if provided
|
||||||
|
if (initial_content && strlen(initial_content) > 0) {
|
||||||
|
FILE* temp_file = fopen(temp_filename, "w");
|
||||||
|
if (temp_file) {
|
||||||
|
fputs(initial_content, temp_file);
|
||||||
|
fclose(temp_file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create empty temp file
|
||||||
|
FILE* temp_file = fopen(temp_filename, "w");
|
||||||
|
if (temp_file) {
|
||||||
|
fclose(temp_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch editor
|
||||||
|
printf("Opening %s for text editing...\n", editor);
|
||||||
|
char command[512];
|
||||||
|
snprintf(command, sizeof(command), "%s %s", editor, temp_filename);
|
||||||
|
|
||||||
|
int result = system(command);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
// Read the edited content back
|
||||||
|
FILE* temp_file = fopen(temp_filename, "r");
|
||||||
|
if (temp_file) {
|
||||||
|
size_t bytes_read = fread(result_buffer, 1, buffer_size - 1, temp_file);
|
||||||
|
result_buffer[bytes_read] = '\0';
|
||||||
|
|
||||||
|
// Remove trailing newline if present
|
||||||
|
if (bytes_read > 0 && result_buffer[bytes_read - 1] == '\n') {
|
||||||
|
result_buffer[bytes_read - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(temp_file);
|
||||||
|
} else {
|
||||||
|
printf("Error: Cannot read edited content\n");
|
||||||
|
free(editor);
|
||||||
|
unlink(temp_filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Editor exited with error or was cancelled\n");
|
||||||
|
free(editor);
|
||||||
|
unlink(temp_filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
unlink(temp_filename);
|
||||||
|
free(editor);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int launch_file_manager(const char* start_directory, char* selected_file, size_t buffer_size) {
|
||||||
|
char* fm = get_preferred_file_manager();
|
||||||
|
if (!fm) {
|
||||||
|
printf("No file manager found. Please install ranger, fzf, nnn, or lf.\n");
|
||||||
|
printf("Falling back to manual file path entry.\n");
|
||||||
|
return 1; // Fall back to manual entry
|
||||||
|
}
|
||||||
|
|
||||||
|
char temp_filename[64];
|
||||||
|
snprintf(temp_filename, sizeof(temp_filename), "/tmp/otp_file_%ld.tmp", time(NULL));
|
||||||
|
|
||||||
|
char command[512];
|
||||||
|
int result = 1;
|
||||||
|
|
||||||
|
printf("Opening %s for file selection...\n", fm);
|
||||||
|
|
||||||
|
if (strcmp(fm, "ranger") == 0) {
|
||||||
|
snprintf(command, sizeof(command), "cd '%s' && ranger --choosefile=%s",
|
||||||
|
start_directory ? start_directory : ".", temp_filename);
|
||||||
|
} else if (strcmp(fm, "fzf") == 0) {
|
||||||
|
snprintf(command, sizeof(command), "cd '%s' && find . -type f | fzf > %s",
|
||||||
|
start_directory ? start_directory : ".", temp_filename);
|
||||||
|
} else if (strcmp(fm, "nnn") == 0) {
|
||||||
|
snprintf(command, sizeof(command), "cd '%s' && nnn -p %s",
|
||||||
|
start_directory ? start_directory : ".", temp_filename);
|
||||||
|
} else if (strcmp(fm, "lf") == 0) {
|
||||||
|
snprintf(command, sizeof(command), "cd '%s' && lf -selection-path=%s",
|
||||||
|
start_directory ? start_directory : ".", temp_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = system(command);
|
||||||
|
|
||||||
|
if (result == 0 || result == 256) { // Some file managers return 256 on success
|
||||||
|
// Read selected file from temp file
|
||||||
|
FILE* temp_file = fopen(temp_filename, "r");
|
||||||
|
if (temp_file) {
|
||||||
|
if (fgets(selected_file, buffer_size, temp_file)) {
|
||||||
|
// Remove trailing newline
|
||||||
|
selected_file[strcspn(selected_file, "\n\r")] = 0;
|
||||||
|
|
||||||
|
// For relative paths from fzf, make absolute if needed
|
||||||
|
if (selected_file[0] == '.' && selected_file[1] == '/') {
|
||||||
|
char current_dir[512];
|
||||||
|
if (getcwd(current_dir, sizeof(current_dir))) {
|
||||||
|
char abs_path[1024];
|
||||||
|
snprintf(abs_path, sizeof(abs_path), "%s/%s", current_dir, selected_file + 2);
|
||||||
|
strncpy(selected_file, abs_path, buffer_size - 1);
|
||||||
|
selected_file[buffer_size - 1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(temp_file);
|
||||||
|
unlink(temp_filename);
|
||||||
|
free(fm);
|
||||||
|
return 0; // Success
|
||||||
|
}
|
||||||
|
fclose(temp_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up and indicate failure
|
||||||
|
unlink(temp_filename);
|
||||||
|
free(fm);
|
||||||
|
return 1; // Fall back to manual entry
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle_text_encrypt(void) {
|
||||||
|
printf("\n=== Text Encrypt ===\n");
|
||||||
|
|
||||||
|
// Launch text editor directly
|
||||||
|
char text_buffer[MAX_INPUT_SIZE];
|
||||||
|
if (launch_text_editor(NULL, text_buffer, sizeof(text_buffer)) != 0) {
|
||||||
|
printf("Error: Could not launch text editor\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(text_buffer) == 0) {
|
||||||
|
printf("No text entered - canceling encryption\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List available pads and get selection
|
||||||
|
int pad_count = list_available_pads();
|
||||||
|
if (pad_count == 0) {
|
||||||
|
printf("No pads available. Generate a pad first.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nEnter pad selection (number, checksum, or prefix): ");
|
||||||
|
char pad_input[MAX_HASH_LENGTH];
|
||||||
|
if (!fgets(pad_input, sizeof(pad_input), stdin)) {
|
||||||
|
printf("Error: Failed to read pad selection\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pad_input[strcspn(pad_input, "\n")] = 0;
|
||||||
|
|
||||||
|
return encrypt_text(pad_input, text_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle_file_encrypt(void) {
|
||||||
|
printf("\n=== File Encrypt ===\n");
|
||||||
|
|
||||||
|
// Launch file manager directly
|
||||||
|
char input_file[512];
|
||||||
|
if (launch_file_manager(".", input_file, sizeof(input_file)) != 0) {
|
||||||
|
printf("Error: Could not launch file manager\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if (access(input_file, R_OK) != 0) {
|
||||||
|
printf("Error: File '%s' not found or cannot be read\n", input_file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List available pads
|
||||||
|
int pad_count = list_available_pads();
|
||||||
|
if (pad_count == 0) {
|
||||||
|
printf("No pads available. Generate a pad first.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nEnter pad selection (number, checksum, or prefix): ");
|
||||||
|
char pad_input[MAX_HASH_LENGTH];
|
||||||
|
if (!fgets(pad_input, sizeof(pad_input), stdin)) {
|
||||||
|
printf("Error: Failed to read pad selection\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pad_input[strcspn(pad_input, "\n")] = 0;
|
||||||
|
|
||||||
|
// Ask for output format
|
||||||
|
printf("\nSelect output format:\n");
|
||||||
|
printf("1. Binary (.otp) - preserves file permissions\n");
|
||||||
|
printf("2. ASCII (.otp.asc) - text-safe format\n");
|
||||||
|
printf("Enter choice (1-2): ");
|
||||||
|
|
||||||
|
char format_input[10];
|
||||||
|
if (!fgets(format_input, sizeof(format_input), stdin)) {
|
||||||
|
printf("Error: Failed to read input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ascii_armor = (atoi(format_input) == 2) ? 1 : 0;
|
||||||
|
|
||||||
|
// Generate default output filename
|
||||||
|
char default_output[1024]; // Increased buffer size to prevent truncation warnings
|
||||||
|
if (ascii_armor) {
|
||||||
|
snprintf(default_output, sizeof(default_output), "%s.otp.asc", input_file);
|
||||||
|
} else {
|
||||||
|
snprintf(default_output, sizeof(default_output), "%s.otp", input_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use enhanced input function for output filename
|
||||||
|
char output_file[512];
|
||||||
|
if (get_filename_with_default("Output filename:", default_output, output_file, sizeof(output_file)) != 0) {
|
||||||
|
printf("Error: Failed to read input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* output_filename = output_file;
|
||||||
|
|
||||||
|
return encrypt_file(pad_input, input_file, output_filename, ascii_armor);
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle_smart_decrypt(void) {
|
||||||
|
printf("\n=== Smart Decrypt ===\n");
|
||||||
|
printf("Enter encrypted data (paste ASCII armor) or press Enter to browse files:\n");
|
||||||
|
|
||||||
|
char input_line[MAX_LINE_LENGTH];
|
||||||
|
if (!fgets(input_line, sizeof(input_line), stdin)) {
|
||||||
|
printf("Error: Failed to read input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove newline
|
||||||
|
input_line[strcspn(input_line, "\n")] = 0;
|
||||||
|
|
||||||
|
if (strlen(input_line) == 0) {
|
||||||
|
// Empty input - launch file manager
|
||||||
|
char selected_file[512];
|
||||||
|
if (launch_file_manager(".", selected_file, sizeof(selected_file)) != 0) {
|
||||||
|
printf("Error: Could not launch file manager\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt selected file
|
||||||
|
return decrypt_file(selected_file, NULL);
|
||||||
|
} else if (strncmp(input_line, "-----BEGIN OTP MESSAGE-----", 27) == 0) {
|
||||||
|
// Looks like ASCII armor - collect the full message
|
||||||
|
char full_message[MAX_INPUT_SIZE * 4] = {0};
|
||||||
|
strcat(full_message, input_line);
|
||||||
|
strcat(full_message, "\n");
|
||||||
|
|
||||||
|
printf("Continue pasting the message (end with -----END OTP MESSAGE-----):\n");
|
||||||
|
|
||||||
|
char line[MAX_LINE_LENGTH];
|
||||||
|
while (fgets(line, sizeof(line), stdin)) {
|
||||||
|
strncat(full_message, line, sizeof(full_message) - strlen(full_message) - 1);
|
||||||
|
if (strstr(line, "-----END OTP MESSAGE-----")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return decrypt_text(NULL, full_message);
|
||||||
|
} else {
|
||||||
|
// Check if it looks like a file path
|
||||||
|
if (access(input_line, R_OK) == 0) {
|
||||||
|
return decrypt_file(input_line, NULL);
|
||||||
|
} else {
|
||||||
|
printf("Input not recognized as ASCII armor or valid file path.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void print_usage(const char* program_name) {
|
void print_usage(const char* program_name) {
|
||||||
printf("OTP Cipher - One Time Pad Implementation %s\n", get_version());
|
printf("OTP Cipher - One Time Pad Implementation %s\n", get_version());
|
||||||
printf("%s\n", get_build_info());
|
printf("%s\n", get_build_info());
|
||||||
|
|||||||
8
otp.code-workspace
Normal file
8
otp.code-workspace
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
||||||
BIN
test.txt.otp
BIN
test.txt.otp
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
This is a test file for OTP encryption.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
-----BEGIN OTP MESSAGE-----
|
|
||||||
Version: v0.2.15
|
|
||||||
Pad-ChkSum: 0c8e19fde996e683fdbd348d1052eec168ffe6f67a88bb1278d0d02e9341b87b
|
|
||||||
Pad-Offset: 210
|
|
||||||
|
|
||||||
mMIm7iVtUO6NbXbskMxtydI/A16UXEQUGTcIya/8Dja6PB3EC0MLdw==
|
|
||||||
-----END OTP MESSAGE-----
|
|
||||||
Reference in New Issue
Block a user