Version v0.3.11 - Add delete option, and TUI improvements
This commit is contained in:
BIN
otp-x86_64
BIN
otp-x86_64
Binary file not shown.
770
otp.c
770
otp.c
@@ -8,6 +8,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
@@ -44,7 +45,6 @@ static const int base64_decode_table[256] = {
|
||||
#define PROGRESS_UPDATE_INTERVAL (64 * 1024 * 1024) // 64MB intervals
|
||||
#define DEFAULT_PADS_DIR "pads"
|
||||
#define FILES_DIR "files"
|
||||
#define MAX_ENTROPY_BUFFER (4 * 1024 * 1024) // 4MB entropy buffer for large operations
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -56,6 +56,60 @@ static char current_pads_dir[512] = DEFAULT_PADS_DIR;
|
||||
static char default_pad_path[1024] = "";
|
||||
static int is_interactive_mode = 0;
|
||||
|
||||
// Terminal dimensions
|
||||
static int terminal_width = 80; // Default fallback width
|
||||
static int terminal_height = 24; // Default fallback height
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMINAL UI FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Initialize terminal dimensions
|
||||
void init_terminal_dimensions(void) {
|
||||
struct winsize ws;
|
||||
|
||||
// Try to get actual terminal size
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0 && ws.ws_row > 0) {
|
||||
terminal_width = ws.ws_col;
|
||||
terminal_height = ws.ws_row;
|
||||
}
|
||||
// If ioctl fails, keep the default values (80x24)
|
||||
}
|
||||
|
||||
// Print centered header with = padding
|
||||
void print_centered_header(const char* text) {
|
||||
if (!text) return;
|
||||
|
||||
int text_len = strlen(text);
|
||||
int available_width = terminal_width;
|
||||
|
||||
// Ensure minimum spacing: at least 1 space on each side
|
||||
int min_required = text_len + 4; // text + " " + text + " " (spaces around text)
|
||||
|
||||
if (available_width < min_required) {
|
||||
// Terminal too narrow - just print the text with minimal formatting
|
||||
printf("=== %s ===\n", text);
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate padding
|
||||
int total_padding = available_width - text_len - 2; // -2 for spaces around text
|
||||
int left_padding = total_padding / 2;
|
||||
int right_padding = total_padding - left_padding;
|
||||
|
||||
// Print the header
|
||||
for (int i = 0; i < left_padding; i++) {
|
||||
printf("=");
|
||||
}
|
||||
printf(" %s ", text);
|
||||
for (int i = 0; i < right_padding; i++) {
|
||||
printf("=");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MAIN
|
||||
@@ -63,7 +117,10 @@ static int is_interactive_mode = 0;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Load preferences first
|
||||
// Initialize terminal dimensions first
|
||||
init_terminal_dimensions();
|
||||
|
||||
// Load preferences
|
||||
load_preferences();
|
||||
|
||||
// Detect interactive mode: only true when running with no arguments
|
||||
@@ -329,9 +386,9 @@ int interactive_mode(void) {
|
||||
|
||||
|
||||
void show_main_menu(void) {
|
||||
|
||||
|
||||
printf("\n=========================== Main Menu - OTP v0.3.9 ===========================\n\n");
|
||||
printf("\n");
|
||||
print_centered_header("Main Menu - OTP v0.3.10");
|
||||
printf("\n");
|
||||
|
||||
printf(" \033[4mT\033[0mext encrypt\n"); //TEXT ENCRYPT
|
||||
printf(" \033[4mF\033[0mile encrypt\n"); //FILE ENCRYPT
|
||||
@@ -342,7 +399,8 @@ void show_main_menu(void) {
|
||||
}
|
||||
|
||||
int handle_generate_menu(void) {
|
||||
printf("\n=== Generate New Pad ===\n");
|
||||
printf("\n");
|
||||
print_centered_header("Generate New Pad");
|
||||
printf("Enter pad size (examples: 1GB, 5TB, 512MB, 2048): ");
|
||||
|
||||
char size_input[64];
|
||||
@@ -367,7 +425,8 @@ int handle_generate_menu(void) {
|
||||
}
|
||||
|
||||
int handle_encrypt_menu(void) {
|
||||
printf("\n=== Encrypt Data ===\n");
|
||||
printf("\n");
|
||||
print_centered_header("Encrypt Data");
|
||||
|
||||
printf("Available pads:\n");
|
||||
char* selected = select_pad_interactive("Available pads:", "Select pad (or press Enter to continue)", PAD_FILTER_ALL, 0);
|
||||
@@ -398,7 +457,7 @@ int handle_encrypt_menu(void) {
|
||||
|
||||
if (choice == 1) {
|
||||
// Text encryption - use unified pad selection
|
||||
char* selected_pad = select_pad_interactive("=== Select Pad for Text Encryption ===",
|
||||
char* selected_pad = select_pad_interactive("Select Pad for Text Encryption",
|
||||
"Select pad (by prefix)",
|
||||
PAD_FILTER_ALL, 1);
|
||||
if (!selected_pad) {
|
||||
@@ -453,7 +512,7 @@ int handle_encrypt_menu(void) {
|
||||
}
|
||||
|
||||
// Use unified pad selection
|
||||
char* selected_pad = select_pad_interactive("=== Select Pad for File Encryption ===",
|
||||
char* selected_pad = select_pad_interactive("Select Pad for File Encryption",
|
||||
"Select pad (by prefix)",
|
||||
PAD_FILTER_ALL, 1);
|
||||
if (!selected_pad) {
|
||||
@@ -508,7 +567,8 @@ int handle_encrypt_menu(void) {
|
||||
}
|
||||
|
||||
int handle_decrypt_menu(void) {
|
||||
printf("\n=== Smart Decrypt ===\n");
|
||||
printf("\n");
|
||||
print_centered_header("Smart Decrypt");
|
||||
printf("Enter encrypted data (paste ASCII armor), file path, or press Enter to browse files:\n");
|
||||
|
||||
char input_line[MAX_LINE_LENGTH];
|
||||
@@ -742,7 +802,7 @@ int show_pad_info(const char* chksum) {
|
||||
uint64_t used_bytes;
|
||||
read_state_offset(chksum, &used_bytes);
|
||||
|
||||
printf("=== Pad Information ===\n");
|
||||
print_centered_header("Pad Information");
|
||||
printf("ChkSum: %s\n", chksum);
|
||||
printf("File: %s\n", pad_filename);
|
||||
|
||||
@@ -1797,6 +1857,136 @@ void get_default_file_path(const char* filename, char* result_path, size_t resul
|
||||
snprintf(result_path, result_size, "%s/%s", files_dir, filename);
|
||||
}
|
||||
|
||||
void get_directory_display(const char* file_path, char* result, size_t result_size) {
|
||||
// Extract directory path from full file path
|
||||
char dir_path[512];
|
||||
char* last_slash = strrchr(file_path, '/');
|
||||
|
||||
if (last_slash) {
|
||||
size_t dir_len = last_slash - file_path;
|
||||
if (dir_len >= sizeof(dir_path)) {
|
||||
dir_len = sizeof(dir_path) - 1;
|
||||
}
|
||||
strncpy(dir_path, file_path, dir_len);
|
||||
dir_path[dir_len] = '\0';
|
||||
} else {
|
||||
// No directory separator, assume current directory
|
||||
strcpy(dir_path, ".");
|
||||
}
|
||||
|
||||
// USB Drive Detection and Smart Shortening
|
||||
char* home_dir = getenv("HOME");
|
||||
|
||||
// Check for USB/removable media mount patterns
|
||||
if (strstr(dir_path, "/media/") || strstr(dir_path, "/run/media/") || strstr(dir_path, "/mnt/")) {
|
||||
// Extract USB label/name
|
||||
char* media_start = NULL;
|
||||
if (strstr(dir_path, "/media/")) {
|
||||
media_start = strstr(dir_path, "/media/");
|
||||
} else if (strstr(dir_path, "/run/media/")) {
|
||||
media_start = strstr(dir_path, "/run/media/");
|
||||
} else if (strstr(dir_path, "/mnt/")) {
|
||||
media_start = strstr(dir_path, "/mnt/");
|
||||
}
|
||||
|
||||
if (media_start) {
|
||||
// Find the USB label part
|
||||
char* path_after_media = strchr(media_start + 1, '/');
|
||||
if (path_after_media) {
|
||||
path_after_media++; // Skip the slash
|
||||
|
||||
// For /media/user/LABEL pattern, skip the username to get to the drive label
|
||||
if (strstr(media_start, "/media/")) {
|
||||
char* next_slash = strchr(path_after_media, '/');
|
||||
if (next_slash) {
|
||||
path_after_media = next_slash + 1;
|
||||
}
|
||||
}
|
||||
// For /run/media/user/LABEL pattern, skip the username
|
||||
else if (strstr(media_start, "/run/media/")) {
|
||||
char* next_slash = strchr(path_after_media, '/');
|
||||
if (next_slash) {
|
||||
path_after_media = next_slash + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract just the USB label (up to next slash or end)
|
||||
char* label_end = strchr(path_after_media, '/');
|
||||
char usb_label[32];
|
||||
if (label_end) {
|
||||
size_t label_len = label_end - path_after_media;
|
||||
if (label_len > sizeof(usb_label) - 1) label_len = sizeof(usb_label) - 1;
|
||||
strncpy(usb_label, path_after_media, label_len);
|
||||
usb_label[label_len] = '\0';
|
||||
} else {
|
||||
// USB label is the last part
|
||||
strncpy(usb_label, path_after_media, sizeof(usb_label) - 1);
|
||||
usb_label[sizeof(usb_label) - 1] = '\0';
|
||||
}
|
||||
|
||||
// Format with USB: prefix, limiting total length to fit in result
|
||||
snprintf(result, result_size, "USB:%s", usb_label);
|
||||
// Truncate if too long
|
||||
if (strlen(result) > 11) {
|
||||
result[11] = '\0';
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Home directory shortening
|
||||
if (home_dir && strncmp(dir_path, home_dir, strlen(home_dir)) == 0) {
|
||||
if (dir_path[strlen(home_dir)] == '/' || dir_path[strlen(home_dir)] == '\0') {
|
||||
// Replace home directory with ~
|
||||
char temp[512];
|
||||
snprintf(temp, sizeof(temp), "~%s", dir_path + strlen(home_dir));
|
||||
|
||||
// If result is too long, truncate intelligently
|
||||
if (strlen(temp) > 11) {
|
||||
// Show ~/...end_part
|
||||
char* last_part = strrchr(temp, '/');
|
||||
if (last_part && strlen(last_part) < 8) {
|
||||
snprintf(result, result_size, "~...%s", last_part);
|
||||
} else {
|
||||
strncpy(result, temp, 11);
|
||||
result[11] = '\0';
|
||||
}
|
||||
} else {
|
||||
strncpy(result, temp, result_size - 1);
|
||||
result[result_size - 1] = '\0';
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Current working directory
|
||||
if (strcmp(dir_path, ".") == 0 || strcmp(dir_path, current_pads_dir) == 0) {
|
||||
strncpy(result, "pads", result_size - 1);
|
||||
result[result_size - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
// System/other paths - smart truncation with ellipsis
|
||||
if (strlen(dir_path) > 11) {
|
||||
// Try to show the most meaningful part
|
||||
char* last_part = strrchr(dir_path, '/');
|
||||
if (last_part && strlen(last_part) < 9) {
|
||||
// Show .../last_part
|
||||
snprintf(result, result_size, "...%s", last_part);
|
||||
} else {
|
||||
// Show first part with ellipsis
|
||||
strncpy(result, dir_path, 8);
|
||||
strncpy(result + 8, "...", result_size - 8 - 1);
|
||||
result[result_size - 1] = '\0';
|
||||
}
|
||||
} else {
|
||||
// Short enough, use as-is
|
||||
strncpy(result, dir_path, result_size - 1);
|
||||
result[result_size - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void get_pad_path(const char* chksum, char* pad_path, char* state_path) {
|
||||
snprintf(pad_path, 1024, "%s/%s.pad", current_pads_dir, chksum);
|
||||
snprintf(state_path, 1024, "%s/%s.state", current_pads_dir, chksum);
|
||||
@@ -2186,36 +2376,9 @@ int detect_otp_thumb_drive(char* otp_drive_path, size_t path_size) {
|
||||
|
||||
|
||||
|
||||
// To be removed
|
||||
// Format file size for display
|
||||
// void format_size_string(uint64_t bytes, char* result, size_t result_size) {
|
||||
// if (bytes == 0) {
|
||||
// strncpy(result, "Unknown", result_size - 1);
|
||||
// result[result_size - 1] = '\0';
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (bytes < 1024) {
|
||||
// snprintf(result, result_size, "%luB", bytes);
|
||||
// } else if (bytes < 1024 * 1024) {
|
||||
// snprintf(result, result_size, "%.1fKB", (double)bytes / 1024.0);
|
||||
// } else if (bytes < 1024 * 1024 * 1024) {
|
||||
// snprintf(result, result_size, "%.1fMB", (double)bytes / (1024.0 * 1024.0));
|
||||
// } else if (bytes < 1024ULL * 1024 * 1024 * 1024) {
|
||||
// snprintf(result, result_size, "%.2fGB", (double)bytes / (1024.0 * 1024.0 * 1024.0));
|
||||
// } else {
|
||||
// snprintf(result, result_size, "%.2fTB", (double)bytes / (1024.0 * 1024.0 * 1024.0 * 1024.0));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Custom base64 encode function
|
||||
|
||||
|
||||
|
||||
char* custom_base64_encode(const unsigned char* input, int length) {
|
||||
int output_length = 4 * ((length + 2) / 3);
|
||||
char* encoded = malloc(output_length + 1);
|
||||
@@ -2551,6 +2714,21 @@ int collect_truerng_entropy(unsigned char* entropy_buffer, size_t target_bytes,
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
// Helper function to format time in human-readable format
|
||||
void format_time_remaining(double seconds, char* buffer, size_t buffer_size) {
|
||||
if (seconds < 60) {
|
||||
snprintf(buffer, buffer_size, "%.0fs", seconds);
|
||||
} else if (seconds < 3600) {
|
||||
int mins = (int)(seconds / 60);
|
||||
int secs = (int)(seconds) % 60;
|
||||
snprintf(buffer, buffer_size, "%dm %02ds", mins, secs);
|
||||
} else {
|
||||
int hours = (int)(seconds / 3600);
|
||||
int mins = (int)(seconds / 60) % 60;
|
||||
snprintf(buffer, buffer_size, "%dh %02dm", hours, mins);
|
||||
}
|
||||
}
|
||||
|
||||
// Streaming TrueRNG entropy collection for full pad enhancement
|
||||
// This function applies entropy directly to the pad in chunks to avoid memory issues
|
||||
int collect_truerng_entropy_streaming(const char* pad_chksum, size_t total_bytes, int display_progress) {
|
||||
@@ -2586,6 +2764,85 @@ int collect_truerng_entropy_streaming(const char* pad_chksum, size_t total_bytes
|
||||
return 2; // Serial port setup failed
|
||||
}
|
||||
|
||||
// For large pads (>10MB), do a 1MB test to estimate completion time
|
||||
double estimated_rate = 0.0;
|
||||
int user_confirmed = 1; // Default to confirmed for small pads
|
||||
|
||||
if (total_bytes > 10 * 1024 * 1024 && display_progress) {
|
||||
printf("\nLarge pad detected (%.1f MB). Running 1MB speed test...\n",
|
||||
(double)total_bytes / (1024.0 * 1024.0));
|
||||
|
||||
// Test with 1MB sample
|
||||
size_t test_bytes = 1024 * 1024; // 1MB
|
||||
unsigned char* test_buffer = malloc(test_bytes);
|
||||
if (!test_buffer) {
|
||||
printf("Error: Cannot allocate test buffer\n");
|
||||
close(serial_fd);
|
||||
return 3;
|
||||
}
|
||||
|
||||
time_t test_start = time(NULL);
|
||||
size_t test_collected = 0;
|
||||
|
||||
while (test_collected < test_bytes) {
|
||||
size_t bytes_needed = test_bytes - test_collected;
|
||||
size_t read_size = (bytes_needed > 1024) ? 1024 : bytes_needed;
|
||||
|
||||
ssize_t result = read(serial_fd, test_buffer + test_collected, read_size);
|
||||
if (result <= 0) {
|
||||
printf("Error: TrueRNG test failed\n");
|
||||
free(test_buffer);
|
||||
close(serial_fd);
|
||||
return 4;
|
||||
}
|
||||
test_collected += result;
|
||||
|
||||
// Show test progress
|
||||
double test_progress = (double)test_collected / test_bytes * 100.0;
|
||||
printf("\rSpeed test: %.1f%% complete", test_progress);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
double test_time = difftime(time(NULL), test_start);
|
||||
estimated_rate = (double)test_bytes / test_time; // bytes per second
|
||||
|
||||
// Calculate estimated total time
|
||||
double estimated_total_time = (double)total_bytes / estimated_rate;
|
||||
|
||||
char time_str[64];
|
||||
format_time_remaining(estimated_total_time, time_str, sizeof(time_str));
|
||||
|
||||
printf("\nSpeed test complete: %.1f KB/s\n", estimated_rate / 1024.0);
|
||||
printf("Estimated completion time: %s\n", time_str);
|
||||
printf("\nProceed with full pad enhancement? (y/N): ");
|
||||
fflush(stdout);
|
||||
|
||||
char response[10];
|
||||
if (fgets(response, sizeof(response), stdin) == NULL ||
|
||||
(response[0] != 'y' && response[0] != 'Y')) {
|
||||
printf("Operation cancelled by user.\n");
|
||||
free(test_buffer);
|
||||
close(serial_fd);
|
||||
return 5; // User cancelled
|
||||
}
|
||||
|
||||
user_confirmed = 1;
|
||||
free(test_buffer);
|
||||
|
||||
// Reset serial port for main operation
|
||||
close(serial_fd);
|
||||
serial_fd = setup_truerng_serial_port(port_path);
|
||||
if (serial_fd < 0) {
|
||||
printf("Error: Cannot reopen TrueRNG device\n");
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
if (!user_confirmed) {
|
||||
close(serial_fd);
|
||||
return 5; // User cancelled
|
||||
}
|
||||
|
||||
// Get pad paths
|
||||
char pad_path[1024];
|
||||
char state_path[1024];
|
||||
@@ -2762,12 +3019,54 @@ int collect_truerng_entropy_streaming(const char* pad_chksum, size_t total_bytes
|
||||
|
||||
bytes_processed += current_chunk_size;
|
||||
|
||||
// Show progress for large pads
|
||||
if (display_progress && bytes_processed % (64 * 1024 * 1024) == 0) { // Every 64MB
|
||||
double percentage = (double)bytes_processed / total_bytes * 100.0;
|
||||
printf("Progress: %.1f%% (%zu/%zu MB)\r", percentage,
|
||||
bytes_processed / (1024*1024), total_bytes / (1024*1024));
|
||||
fflush(stdout);
|
||||
// Show progress and entropy samples for visual verification
|
||||
if (display_progress) {
|
||||
// Update progress more frequently for better user experience - always show cumulative amount
|
||||
if (bytes_processed % (4 * 1024 * 1024) == 0 || bytes_processed == total_bytes) { // Every 4MB or at completion
|
||||
double percentage = (double)bytes_processed / total_bytes * 100.0;
|
||||
double elapsed = difftime(time(NULL), start_time);
|
||||
double rate = 0.0;
|
||||
if (elapsed > 0) {
|
||||
rate = (double)bytes_processed / elapsed / (1024.0 * 1024.0);
|
||||
}
|
||||
|
||||
// Calculate estimated time remaining
|
||||
char eta_str[64] = "";
|
||||
if (rate > 0.0 && bytes_processed < total_bytes) {
|
||||
double remaining_bytes = (double)(total_bytes - bytes_processed);
|
||||
double eta_seconds = remaining_bytes / (rate * 1024.0 * 1024.0); // Convert rate back to bytes/sec
|
||||
format_time_remaining(eta_seconds, eta_str, sizeof(eta_str));
|
||||
}
|
||||
|
||||
// Clear previous line and show progress bar with cumulative TrueRNG data generated
|
||||
printf("\r\033[K"); // Clear line
|
||||
printf("[");
|
||||
int bar_width = 30;
|
||||
int filled = (int)(percentage / 100.0 * bar_width);
|
||||
for (int i = 0; i < filled; i++) printf("█");
|
||||
for (int i = filled; i < bar_width; i++) printf("░");
|
||||
|
||||
if (strlen(eta_str) > 0) {
|
||||
printf("] %.1f%% - TrueRNG: %zu MB / %zu MB (%.1f MB/s) ETA: %s",
|
||||
percentage, bytes_processed / (1024*1024), total_bytes / (1024*1024), rate, eta_str);
|
||||
} else {
|
||||
printf("] %.1f%% - TrueRNG: %zu MB / %zu MB (%.1f MB/s)",
|
||||
percentage, bytes_processed / (1024*1024), total_bytes / (1024*1024), rate);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// Show entropy samples every 64MB for visual verification of randomness
|
||||
if (bytes_processed % (64 * 1024 * 1024) == 0 && bytes_processed > 0) {
|
||||
printf("\n🔬 TrueRNG entropy sample: ");
|
||||
// Display first 16 bytes of current entropy chunk as hex
|
||||
size_t sample_size = (current_chunk_size < 16) ? current_chunk_size : 16;
|
||||
for (size_t i = 0; i < sample_size; i++) {
|
||||
printf("%02x", entropy_chunk[i]);
|
||||
if (i == 7) printf(" "); // Space in middle for readability
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2805,7 +3104,7 @@ int collect_truerng_entropy_streaming(const char* pad_chksum, size_t total_bytes
|
||||
int collect_dice_entropy(unsigned char* entropy_buffer, size_t target_bytes,
|
||||
size_t* collected_bytes, int display_progress) {
|
||||
if (display_progress) {
|
||||
printf("=== Dice Entropy Collection ===\n");
|
||||
print_centered_header("Dice Entropy Collection");
|
||||
printf("Enter dice rolls as sequences of digits 1-6.\n");
|
||||
printf("Target: %zu bytes (%zu dice rolls needed)\n", target_bytes, target_bytes * 4);
|
||||
printf("Press Enter after each sequence, or 'done' when finished.\n\n");
|
||||
@@ -3493,7 +3792,7 @@ int generate_ascii_armor(const char* chksum, uint64_t offset, const unsigned cha
|
||||
strcpy(*ascii_output, "-----BEGIN OTP MESSAGE-----\n");
|
||||
|
||||
char temp_line[256];
|
||||
snprintf(temp_line, sizeof(temp_line), "Version: v0.3.9\n");
|
||||
snprintf(temp_line, sizeof(temp_line), "Version: v0.3.10\n");
|
||||
strcat(*ascii_output, temp_line);
|
||||
|
||||
snprintf(temp_line, sizeof(temp_line), "Pad-ChkSum: %s\n", chksum);
|
||||
@@ -4157,7 +4456,8 @@ int launch_file_manager(const char* start_directory, char* selected_file, size_t
|
||||
}
|
||||
|
||||
int handle_text_encrypt(void) {
|
||||
printf("\n=== Text Encrypt ===\n");
|
||||
printf("\n");
|
||||
print_centered_header("Text Encrypt");
|
||||
|
||||
// Launch text editor directly
|
||||
char text_buffer[MAX_INPUT_SIZE];
|
||||
@@ -4172,7 +4472,7 @@ int handle_text_encrypt(void) {
|
||||
}
|
||||
|
||||
// Use unified pad selection
|
||||
char* selected_pad = select_pad_interactive("=== Select Pad for Text Encryption ===",
|
||||
char* selected_pad = select_pad_interactive("Select Pad for Text Encryption",
|
||||
"Select pad (by prefix)",
|
||||
PAD_FILTER_ALL, 1);
|
||||
if (!selected_pad) {
|
||||
@@ -4186,7 +4486,8 @@ int handle_text_encrypt(void) {
|
||||
}
|
||||
|
||||
int handle_file_encrypt(void) {
|
||||
printf("\n=== File Encrypt ===\n");
|
||||
printf("\n");
|
||||
print_centered_header("File Encrypt");
|
||||
|
||||
// Launch file manager directly
|
||||
char input_file[512];
|
||||
@@ -4202,7 +4503,7 @@ int handle_file_encrypt(void) {
|
||||
}
|
||||
|
||||
// Use unified pad selection
|
||||
char* selected_pad = select_pad_interactive("=== Select Pad for File Encryption ===",
|
||||
char* selected_pad = select_pad_interactive("Select Pad for File Encryption",
|
||||
"Select pad (by prefix)",
|
||||
PAD_FILTER_ALL, 1);
|
||||
if (!selected_pad) {
|
||||
@@ -4373,7 +4674,7 @@ char* select_pad_interactive(const char* title, const char* prompt, pad_filter_t
|
||||
pads[pad_count].percentage = (double)used_bytes / st.st_size * 100.0;
|
||||
|
||||
// Set location info using directory display
|
||||
// get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location));
|
||||
get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location));
|
||||
|
||||
pad_count++;
|
||||
}
|
||||
@@ -4543,7 +4844,8 @@ char* select_pad_interactive(const char* title, const char* prompt, pad_filter_t
|
||||
}
|
||||
|
||||
int handle_pads_menu(void) {
|
||||
printf("\n=== Pad Management ===\n");
|
||||
printf("\n");
|
||||
print_centered_header("Pad Management");
|
||||
|
||||
// Get list of pads from current directory
|
||||
DIR* dir = opendir(current_pads_dir);
|
||||
@@ -4606,7 +4908,7 @@ int handle_pads_menu(void) {
|
||||
pads[pad_count].percentage = (double)used_bytes / st.st_size * 100.0;
|
||||
|
||||
// Set location info using directory display
|
||||
// get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location));
|
||||
get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location));
|
||||
|
||||
pad_count++;
|
||||
}
|
||||
@@ -4712,6 +5014,8 @@ int handle_pads_menu(void) {
|
||||
printf("\nActions:\n");
|
||||
printf(" \033[4mG\033[0menerate new pad\n");
|
||||
printf(" \033[4mA\033[0mdd entropy to pad\n");
|
||||
printf(" \033[4mV\033[0merify pad integrity\n");
|
||||
printf(" \033[4mD\033[0melete pad\n");
|
||||
printf(" \033[4mS\033[0met default pad\n");
|
||||
printf(" E\033[4mx\033[0mit\n");
|
||||
printf("\nSelect action: ");
|
||||
@@ -4733,7 +5037,7 @@ int handle_pads_menu(void) {
|
||||
return result;
|
||||
} else if (toupper(input[0]) == 'A') {
|
||||
// Add entropy to pad - use unified function with unused pads filter
|
||||
char* selected_pad = select_pad_interactive("=== Select Unused Pad for Entropy Addition ===",
|
||||
char* selected_pad = select_pad_interactive("Select Unused Pad for Entropy Addition",
|
||||
"Select unused pad (by prefix)",
|
||||
PAD_FILTER_UNUSED_ONLY, 1);
|
||||
if (!selected_pad) {
|
||||
@@ -4749,9 +5053,37 @@ int handle_pads_menu(void) {
|
||||
return handle_pads_menu();
|
||||
}
|
||||
return result;
|
||||
} else if (toupper(input[0]) == 'V') {
|
||||
// Verify pad integrity - use unified function
|
||||
char* selected_pad = select_pad_interactive("Select Pad for Verification",
|
||||
"Select pad to verify (by prefix)",
|
||||
PAD_FILTER_ALL, 1);
|
||||
if (!selected_pad) {
|
||||
printf("Pad verification cancelled.\n");
|
||||
return handle_pads_menu();
|
||||
}
|
||||
|
||||
// Verify the selected pad
|
||||
handle_verify_pad(selected_pad);
|
||||
free(selected_pad);
|
||||
return handle_pads_menu(); // Always return to pads menu after verification
|
||||
} else if (toupper(input[0]) == 'D') {
|
||||
// Delete pad - use unified function
|
||||
char* selected_pad = select_pad_interactive("Select Pad for Deletion",
|
||||
"Select pad to delete (by prefix)",
|
||||
PAD_FILTER_ALL, 1);
|
||||
if (!selected_pad) {
|
||||
printf("Pad deletion cancelled.\n");
|
||||
return handle_pads_menu();
|
||||
}
|
||||
|
||||
// Delete the selected pad
|
||||
handle_delete_pad(selected_pad);
|
||||
free(selected_pad);
|
||||
return handle_pads_menu(); // Always return to pads menu after deletion attempt
|
||||
} else if (toupper(input[0]) == 'S') {
|
||||
// Set default pad - use unified function
|
||||
char* selected_pad = select_pad_interactive("=== Select Default Pad ===",
|
||||
char* selected_pad = select_pad_interactive("Select Default Pad",
|
||||
"Select pad to set as default (by prefix)",
|
||||
PAD_FILTER_ALL, 1);
|
||||
if (!selected_pad) {
|
||||
@@ -4811,139 +5143,11 @@ int handle_pads_menu(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// To be removed
|
||||
// void get_directory_display(const char* file_path, char* result, size_t result_size) {
|
||||
// // Extract directory path from full file path
|
||||
// char dir_path[512];
|
||||
// char* last_slash = strrchr(file_path, '/');
|
||||
|
||||
// if (last_slash) {
|
||||
// size_t dir_len = last_slash - file_path;
|
||||
// if (dir_len >= sizeof(dir_path)) {
|
||||
// dir_len = sizeof(dir_path) - 1;
|
||||
// }
|
||||
// strncpy(dir_path, file_path, dir_len);
|
||||
// dir_path[dir_len] = '\0';
|
||||
// } else {
|
||||
// // No directory separator, assume current directory
|
||||
// strcpy(dir_path, ".");
|
||||
// }
|
||||
|
||||
// // USB Drive Detection and Smart Shortening
|
||||
// char* home_dir = getenv("HOME");
|
||||
|
||||
// // Check for USB/removable media mount patterns
|
||||
// if (strstr(dir_path, "/media/") || strstr(dir_path, "/run/media/") || strstr(dir_path, "/mnt/")) {
|
||||
// // Extract USB label/name
|
||||
// char* media_start = NULL;
|
||||
// if (strstr(dir_path, "/media/")) {
|
||||
// media_start = strstr(dir_path, "/media/");
|
||||
// } else if (strstr(dir_path, "/run/media/")) {
|
||||
// media_start = strstr(dir_path, "/run/media/");
|
||||
// } else if (strstr(dir_path, "/mnt/")) {
|
||||
// media_start = strstr(dir_path, "/mnt/");
|
||||
// }
|
||||
|
||||
// if (media_start) {
|
||||
// // Find the USB label part
|
||||
// char* path_after_media = strchr(media_start + 1, '/');
|
||||
// if (path_after_media) {
|
||||
// path_after_media++; // Skip the slash
|
||||
|
||||
// // For /media/user/LABEL pattern, skip the username to get to the drive label
|
||||
// if (strstr(media_start, "/media/")) {
|
||||
// char* next_slash = strchr(path_after_media, '/');
|
||||
// if (next_slash) {
|
||||
// path_after_media = next_slash + 1;
|
||||
// }
|
||||
// }
|
||||
// // For /run/media/user/LABEL pattern, skip the username
|
||||
// else if (strstr(media_start, "/run/media/")) {
|
||||
// char* next_slash = strchr(path_after_media, '/');
|
||||
// if (next_slash) {
|
||||
// path_after_media = next_slash + 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Extract just the USB label (up to next slash or end)
|
||||
// char* label_end = strchr(path_after_media, '/');
|
||||
// char usb_label[32];
|
||||
// if (label_end) {
|
||||
// size_t label_len = label_end - path_after_media;
|
||||
// if (label_len > sizeof(usb_label) - 1) label_len = sizeof(usb_label) - 1;
|
||||
// strncpy(usb_label, path_after_media, label_len);
|
||||
// usb_label[label_len] = '\0';
|
||||
// } else {
|
||||
// // USB label is the last part
|
||||
// strncpy(usb_label, path_after_media, sizeof(usb_label) - 1);
|
||||
// usb_label[sizeof(usb_label) - 1] = '\0';
|
||||
// }
|
||||
|
||||
// // Format with USB: prefix, limiting total length to fit in result
|
||||
// snprintf(result, result_size, "USB:%s", usb_label);
|
||||
// // Truncate if too long
|
||||
// if (strlen(result) > 11) {
|
||||
// result[11] = '\0';
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Home directory shortening
|
||||
// if (home_dir && strncmp(dir_path, home_dir, strlen(home_dir)) == 0) {
|
||||
// if (dir_path[strlen(home_dir)] == '/' || dir_path[strlen(home_dir)] == '\0') {
|
||||
// // Replace home directory with ~
|
||||
// char temp[512];
|
||||
// snprintf(temp, sizeof(temp), "~%s", dir_path + strlen(home_dir));
|
||||
|
||||
// // If result is too long, truncate intelligently
|
||||
// if (strlen(temp) > 11) {
|
||||
// // Show ~/...end_part
|
||||
// char* last_part = strrchr(temp, '/');
|
||||
// if (last_part && strlen(last_part) < 8) {
|
||||
// snprintf(result, result_size, "~...%s", last_part);
|
||||
// } else {
|
||||
// strncpy(result, temp, 11);
|
||||
// result[11] = '\0';
|
||||
// }
|
||||
// } else {
|
||||
// strncpy(result, temp, result_size - 1);
|
||||
// result[result_size - 1] = '\0';
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Current working directory
|
||||
// if (strcmp(dir_path, ".") == 0 || strcmp(dir_path, current_pads_dir) == 0) {
|
||||
// strncpy(result, "pads", result_size - 1);
|
||||
// result[result_size - 1] = '\0';
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // System/other paths - smart truncation with ellipsis
|
||||
// if (strlen(dir_path) > 11) {
|
||||
// // Try to show the most meaningful part
|
||||
// char* last_part = strrchr(dir_path, '/');
|
||||
// if (last_part && strlen(last_part) < 9) {
|
||||
// // Show .../last_part
|
||||
// snprintf(result, result_size, "...%s", last_part);
|
||||
// } else {
|
||||
// // Show first part with ellipsis
|
||||
// strncpy(result, dir_path, 8);
|
||||
// strncpy(result + 8, "...", result_size - 8 - 1);
|
||||
// result[result_size - 1] = '\0';
|
||||
// }
|
||||
// } else {
|
||||
// // Short enough, use as-is
|
||||
// strncpy(result, dir_path, result_size - 1);
|
||||
// result[result_size - 1] = '\0';
|
||||
// }
|
||||
// }
|
||||
|
||||
int handle_add_entropy_to_pad(const char* pad_chksum) {
|
||||
printf("\n=== Add Entropy to Pad: %.16s... ===\n", pad_chksum);
|
||||
char header_text[128];
|
||||
snprintf(header_text, sizeof(header_text), "Add Entropy to Pad: %.16s...", pad_chksum);
|
||||
printf("\n");
|
||||
print_centered_header(header_text);
|
||||
|
||||
// Present entropy source selection menu with consistent formatting
|
||||
printf("Select entropy source:\n");
|
||||
@@ -5130,9 +5334,199 @@ int handle_add_entropy_to_pad(const char* pad_chksum) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_verify_pad(const char* pad_chksum) {
|
||||
char header_text[128];
|
||||
snprintf(header_text, sizeof(header_text), "Verify Pad Integrity: %.16s...", pad_chksum);
|
||||
printf("\n");
|
||||
print_centered_header(header_text);
|
||||
|
||||
// Construct pad file path
|
||||
char pad_path[1024];
|
||||
char state_path[1024];
|
||||
get_pad_path(pad_chksum, pad_path, state_path);
|
||||
|
||||
// Check if pad file exists
|
||||
if (access(pad_path, R_OK) != 0) {
|
||||
printf("❌ ERROR: Pad file not found: %s\n", pad_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Calculating pad checksum...\n");
|
||||
|
||||
// Calculate actual checksum of the pad file
|
||||
char calculated_checksum[65];
|
||||
if (calculate_checksum(pad_path, calculated_checksum) != 0) {
|
||||
printf("❌ ERROR: Failed to calculate pad checksum\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Compare calculated checksum with filename (expected checksum)
|
||||
if (strcmp(pad_chksum, calculated_checksum) == 0) {
|
||||
printf("✅ SUCCESS: Pad integrity verified!\n");
|
||||
printf(" Expected: %.16s...\n", pad_chksum);
|
||||
printf(" Actual: %.16s...\n", calculated_checksum);
|
||||
printf(" Status: MATCH - Pad is intact and valid\n");
|
||||
|
||||
// Get additional pad info
|
||||
struct stat pad_stat;
|
||||
if (stat(pad_path, &pad_stat) == 0) {
|
||||
uint64_t used_bytes;
|
||||
read_state_offset(pad_chksum, &used_bytes);
|
||||
|
||||
double size_gb = (double)pad_stat.st_size / (1024.0 * 1024.0 * 1024.0);
|
||||
double used_gb = (double)used_bytes / (1024.0 * 1024.0 * 1024.0);
|
||||
double usage_percent = (double)used_bytes / pad_stat.st_size * 100.0;
|
||||
|
||||
printf(" Size: %.2f GB (%lu bytes)\n", size_gb, pad_stat.st_size);
|
||||
printf(" Used: %.2f GB (%lu bytes)\n", used_gb, used_bytes);
|
||||
printf(" Usage: %.1f%%\n", usage_percent);
|
||||
}
|
||||
|
||||
printf("\n✅ This pad is safe to use for encryption.\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("❌ FAILURE: Pad integrity check failed!\n");
|
||||
printf(" Expected: %.16s...\n", pad_chksum);
|
||||
printf(" Actual: %.16s...\n", calculated_checksum);
|
||||
printf(" Status: MISMATCH - Pad may be corrupted!\n");
|
||||
printf("\n⚠️ WARNING: This pad should NOT be used for encryption.\n");
|
||||
printf(" The pad file may have been modified or corrupted.\n");
|
||||
printf(" Consider regenerating this pad or using a different one.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int handle_delete_pad(const char* pad_chksum) {
|
||||
char header_text[128];
|
||||
snprintf(header_text, sizeof(header_text), "Delete Pad: %.16s...", pad_chksum);
|
||||
printf("\n");
|
||||
print_centered_header(header_text);
|
||||
|
||||
// Construct pad and state file paths
|
||||
char pad_path[1024];
|
||||
char state_path[1024];
|
||||
get_pad_path(pad_chksum, pad_path, state_path);
|
||||
|
||||
// Check if pad file exists
|
||||
if (access(pad_path, F_OK) != 0) {
|
||||
printf("❌ ERROR: Pad file not found: %s\n", pad_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get pad information for display
|
||||
struct stat pad_stat;
|
||||
if (stat(pad_path, &pad_stat) == 0) {
|
||||
uint64_t used_bytes;
|
||||
read_state_offset(pad_chksum, &used_bytes);
|
||||
|
||||
double size_gb = (double)pad_stat.st_size / (1024.0 * 1024.0 * 1024.0);
|
||||
double used_gb = (double)used_bytes / (1024.0 * 1024.0 * 1024.0);
|
||||
double usage_percent = (double)used_bytes / pad_stat.st_size * 100.0;
|
||||
|
||||
printf("Pad Information:\n");
|
||||
printf(" Checksum: %s\n", pad_chksum);
|
||||
printf(" Size: %.2f GB (%lu bytes)\n", size_gb, pad_stat.st_size);
|
||||
printf(" Used: %.2f GB (%lu bytes)\n", used_gb, used_bytes);
|
||||
printf(" Usage: %.1f%%\n", usage_percent);
|
||||
printf(" Path: %s\n", pad_path);
|
||||
}
|
||||
|
||||
// Check if this is the default pad
|
||||
char* current_default = get_default_pad_path();
|
||||
int is_default_pad = 0;
|
||||
if (current_default) {
|
||||
// Check if the pad to be deleted is the current default
|
||||
if (strstr(current_default, pad_chksum)) {
|
||||
is_default_pad = 1;
|
||||
printf(" Status: ⚠️ This is your DEFAULT pad\n");
|
||||
}
|
||||
free(current_default);
|
||||
}
|
||||
|
||||
// Warning and confirmation
|
||||
printf("\n⚠️ WARNING: This action cannot be undone!\n");
|
||||
if (is_default_pad) {
|
||||
printf("⚠️ Deleting the default pad will require setting a new default.\n");
|
||||
}
|
||||
printf("\nAre you absolutely sure you want to delete this pad? (y/N): ");
|
||||
|
||||
char response[10];
|
||||
if (!fgets(response, sizeof(response), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Require explicit 'y' or 'Y' to proceed
|
||||
if (response[0] != 'y' && response[0] != 'Y') {
|
||||
printf("Pad deletion cancelled.\n");
|
||||
return 0; // User cancelled - not an error
|
||||
}
|
||||
|
||||
// Double confirmation for extra safety
|
||||
printf("\nFinal confirmation - type 'DELETE' to proceed: ");
|
||||
char final_response[20];
|
||||
if (!fgets(final_response, sizeof(final_response), stdin)) {
|
||||
printf("Error: Failed to read input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Remove newline
|
||||
final_response[strcspn(final_response, "\n")] = 0;
|
||||
|
||||
if (strcmp(final_response, "DELETE") != 0) {
|
||||
printf("Confirmation text did not match. Pad deletion cancelled.\n");
|
||||
return 0; // User didn't confirm - not an error
|
||||
}
|
||||
|
||||
// Proceed with deletion
|
||||
printf("\nDeleting pad files...\n");
|
||||
|
||||
// Delete pad file
|
||||
if (unlink(pad_path) != 0) {
|
||||
printf("❌ ERROR: Failed to delete pad file: %s\n", pad_path);
|
||||
perror("unlink");
|
||||
return 1;
|
||||
} else {
|
||||
printf("✅ Deleted pad file: %s\n", pad_path);
|
||||
}
|
||||
|
||||
// Delete state file (if it exists)
|
||||
if (access(state_path, F_OK) == 0) {
|
||||
if (unlink(state_path) != 0) {
|
||||
printf("⚠️ WARNING: Failed to delete state file: %s\n", state_path);
|
||||
perror("unlink");
|
||||
// Continue - pad file was deleted successfully
|
||||
} else {
|
||||
printf("✅ Deleted state file: %s\n", state_path);
|
||||
}
|
||||
} else {
|
||||
printf("ℹ️ No state file found (this is normal)\n");
|
||||
}
|
||||
|
||||
// Handle default pad update if necessary
|
||||
if (is_default_pad) {
|
||||
printf("\n🔄 Updating default pad preference...\n");
|
||||
|
||||
// Clear the current default pad
|
||||
if (set_preference("default_pad", NULL) == 0) {
|
||||
printf("✅ Default pad preference cleared\n");
|
||||
printf("ℹ️ You can set a new default pad from the pad management menu\n");
|
||||
} else {
|
||||
printf("⚠️ WARNING: Failed to clear default pad preference\n");
|
||||
printf(" You may need to manually update your configuration\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n✅ SUCCESS: Pad deleted successfully!\n");
|
||||
printf(" Checksum: %.16s...\n", pad_chksum);
|
||||
printf(" Both pad and state files have been removed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void print_usage(const char* program_name) {
|
||||
printf("OTP Cipher - One Time Pad Implementation v0.3.9\n");
|
||||
printf("OTP Cipher - One Time Pad Implementation v0.3.10\n");
|
||||
printf("Built for testing entropy system\n");
|
||||
printf("Usage:\n");
|
||||
printf(" %s - Interactive mode\n", program_name);
|
||||
|
||||
12
otp.h
12
otp.h
@@ -29,7 +29,7 @@
|
||||
#define PROGRESS_UPDATE_INTERVAL (64 * 1024 * 1024) // 64MB intervals
|
||||
#define DEFAULT_PADS_DIR "pads"
|
||||
#define FILES_DIR "files"
|
||||
#define MAX_ENTROPY_BUFFER 32768 // 32KB entropy buffer
|
||||
#define MAX_ENTROPY_BUFFER (4 * 1024 * 1024) // 4MB entropy buffer for large operations
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TYPE DEFINITIONS
|
||||
@@ -248,6 +248,14 @@ int universal_decrypt(const char* input_data, const char* output_target, decrypt
|
||||
char* custom_base64_encode(const unsigned char* input, int length);
|
||||
unsigned char* custom_base64_decode(const char* input, int* output_length);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMINAL UI FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Terminal dimension and UI functions
|
||||
void init_terminal_dimensions(void);
|
||||
void print_centered_header(const char* text);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MENU SYSTEM FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -260,6 +268,8 @@ int handle_decrypt_menu(void);
|
||||
int handle_pads_menu(void);
|
||||
int handle_text_encrypt(void);
|
||||
int handle_file_encrypt(void);
|
||||
int handle_verify_pad(const char* pad_chksum);
|
||||
int handle_delete_pad(const char* pad_chksum);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ENHANCED INPUT FUNCTIONS
|
||||
|
||||
Reference in New Issue
Block a user