Compare commits

...

2 Commits

Author SHA1 Message Date
ae0afcfffd Version v0.2.14 - small fix 2025-08-10 10:16:33 -04:00
e45aa04b05 Version v0.2.13 - Some more changes to build.sh 2025-08-10 09:57:47 -04:00
4 changed files with 157 additions and 68 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
otp
pads/ pads/
Gemini.md Gemini.md

View File

@@ -200,3 +200,4 @@ When contributing:
2. For major features, consider manually creating minor version tags 2. For major features, consider manually creating minor version tags
3. Generated version files (`src/version.*`, `VERSION`) should not be committed 3. Generated version files (`src/version.*`, `VERSION`) should not be committed
# Test change # Test change
# Testing -m flag

View File

@@ -13,6 +13,23 @@ print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; } print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Global variable for commit message
COMMIT_MESSAGE=""
# Parse command line arguments for -m flag
while [[ $# -gt 0 ]]; do
case $1 in
-m|--message)
COMMIT_MESSAGE="$2"
shift 2
;;
*)
# Keep other arguments for main logic
break
;;
esac
done
# Function to automatically increment version # Function to automatically increment version
increment_version() { increment_version() {
print_status "Incrementing version..." print_status "Incrementing version..."
@@ -57,16 +74,18 @@ increment_version() {
print_warning "Failed to stage changes (maybe not a git repository)" print_warning "Failed to stage changes (maybe not a git repository)"
fi fi
# Prompt for commit message # Handle commit message - use global variable if set, otherwise prompt
echo "" if [[ -z "$COMMIT_MESSAGE" ]]; then
print_status "Please enter a meaningful commit message for version $NEW_VERSION:" echo ""
echo -n "> " print_status "Please enter a meaningful commit message for version $NEW_VERSION:"
read -r COMMIT_MESSAGE echo -n "> "
read -r COMMIT_MESSAGE
fi
# Check if user provided a message # Check if user provided a message
if [[ -z "$COMMIT_MESSAGE" ]]; then if [[ -z "$COMMIT_MESSAGE" ]]; then
print_warning "No commit message provided. Using default message." print_warning "No commit message provided. Using default message."
COMMIT_MESSAGE="Version $NEW_VERSION - Automatic version increment" COMMIT_MESSAGE="Automatic version increment"
fi fi
# Commit changes with user-provided message # Commit changes with user-provided message
@@ -239,7 +258,10 @@ case "${1:-build}" in
;; ;;
*) *)
echo "OTP Cipher Build Script" echo "OTP Cipher Build Script"
echo "Usage: $0 {build|static|clean|install|uninstall|version}" echo "Usage: $0 [-m \"commit message\"] {build|static|clean|install|uninstall|version}"
echo ""
echo "Options:"
echo " -m, --message \"text\" - Specify commit message (skips interactive prompt)"
echo "" echo ""
echo "Commands:" echo "Commands:"
echo " build - Build project with automatic version increment (default)" echo " build - Build project with automatic version increment (default)"
@@ -248,6 +270,11 @@ case "${1:-build}" in
echo " install - Install to system (requires build first)" echo " install - Install to system (requires build first)"
echo " uninstall - Remove from system" echo " uninstall - Remove from system"
echo " version - Generate version files only" echo " version - Generate version files only"
echo ""
echo "Examples:"
echo " $0 build"
echo " $0 -m \"Fixed checksum parsing bug\" build"
echo " $0 --message \"Added new feature\" static"
exit 1 exit 1
;; ;;
esac esac

178
otp.c
View File

@@ -50,8 +50,8 @@ int command_line_mode(int argc, char* argv[]);
// 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);
int encrypt_text(const char* pad_identifier); int encrypt_text(const char* pad_identifier, const char* input_text);
int decrypt_text(const char* pad_identifier); int decrypt_text(const char* pad_identifier, const char* encrypted_message);
// Keyboard entropy functions // Keyboard entropy functions
int setup_raw_terminal(struct termios* original_termios); 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 return generate_pad_with_entropy(size, 1, 0); // No keyboard entropy for command line
} }
else if (strcmp(argv[1], "encrypt") == 0) { else if (strcmp(argv[1], "encrypt") == 0) {
if (argc != 3) { if (argc < 3 || argc > 4) {
printf("Usage: %s encrypt <pad_chksum_or_prefix>\n", argv[0]); printf("Usage: %s encrypt <pad_chksum_or_prefix> [text_to_encrypt]\n", argv[0]);
return 1; 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) { else if (strcmp(argv[1], "decrypt") == 0) {
if (argc != 3) { if (argc < 3 || argc > 4) {
printf("Usage: %s decrypt <pad_chksum_or_prefix>\n", argv[0]); printf("Usage: %s decrypt <pad_chksum_or_prefix> [encrypted_message]\n", argv[0]);
return 1; 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) { else if (strcmp(argv[1], "list") == 0) {
return list_available_pads(); return list_available_pads();
@@ -250,12 +254,12 @@ int handle_encrypt_menu(void) {
} }
input[strcspn(input, "\n")] = 0; input[strcspn(input, "\n")] = 0;
return encrypt_text(input); return encrypt_text(input, NULL); // NULL for interactive mode
} }
int handle_decrypt_menu(void) { int handle_decrypt_menu(void) {
printf("\n=== Decrypt Message ===\n"); 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) { 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; 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); char* pad_chksum = find_pad_by_prefix(pad_identifier);
if (!pad_chksum) { if (!pad_chksum) {
return 1; return 1;
} }
char input_text[MAX_INPUT_SIZE]; char text_buffer[MAX_INPUT_SIZE];
char chksum_hex[MAX_HASH_LENGTH]; char chksum_hex[MAX_HASH_LENGTH];
uint64_t current_offset; uint64_t current_offset;
@@ -841,23 +845,30 @@ int encrypt_text(const char* pad_identifier) {
return 1; return 1;
} }
// Get input text from user // Get input text - either from parameter or user input
printf("Enter text to encrypt: "); if (input_text != NULL) {
fflush(stdout); // 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(input_text, sizeof(input_text), stdin) == NULL) { if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) {
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 // Remove newline if present
size_t input_len = strlen(input_text); size_t len = strlen(text_buffer);
if (input_len > 0 && input_text[input_len - 1] == '\n') { if (len > 0 && text_buffer[len - 1] == '\n') {
input_text[input_len - 1] = '\0'; text_buffer[len - 1] = '\0';
input_len--; }
} }
size_t input_len = strlen(text_buffer);
if (input_len == 0) { if (input_len == 0) {
printf("Error: No input provided\n"); printf("Error: No input provided\n");
free(pad_chksum); free(pad_chksum);
@@ -908,7 +919,7 @@ int encrypt_text(const char* pad_identifier) {
// XOR encrypt the input // XOR encrypt the input
unsigned char* ciphertext = malloc(input_len); unsigned char* ciphertext = malloc(input_len);
for (size_t i = 0; i < input_len; i++) { 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 // Encode as base64
@@ -943,7 +954,7 @@ int encrypt_text(const char* pad_identifier) {
return 0; 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 // For command line mode, pad_identifier is ignored - we'll get the chksum from the message
(void)pad_identifier; // Suppress unused parameter warning (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}; char base64_data[MAX_INPUT_SIZE * 2] = {0};
int in_data_section = 0; int in_data_section = 0;
printf("Enter encrypted message (paste the full ASCII armor block):\n"); if (encrypted_message != NULL) {
// Parse provided encrypted message
char *message_copy = strdup(encrypted_message);
char *line_ptr = strtok(message_copy, "\n");
// Read the ASCII armor format int found_begin = 0;
int found_begin = 0; while (line_ptr != NULL) {
while (fgets(line, sizeof(line), stdin)) { if (strcmp(line_ptr, "-----BEGIN OTP MESSAGE-----") == 0) {
line[strcspn(line, "\n")] = 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 (strcmp(line, "-----BEGIN OTP MESSAGE-----") == 0) { if (!found_begin) {
found_begin = 1; printf("Error: Invalid message format - missing BEGIN header\n");
continue; 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) { if (!found_begin) {
break; printf("Error: Invalid message format - missing BEGIN header\n");
} return 1;
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);
} }
} }
@@ -1345,11 +1400,16 @@ 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());
printf("Usage:\n"); printf("Usage:\n");
printf(" %s - Interactive mode\n", program_name); printf(" %s - Interactive mode\n", program_name);
printf(" %s generate <size> - Generate new pad\n", program_name); printf(" %s generate <size> - Generate new pad\n", program_name);
printf(" %s encrypt <pad_checksum_prefix> - Encrypt text\n", program_name); printf(" %s encrypt <pad_checksum_prefix> [text] - Encrypt text\n", program_name);
printf(" %s decrypt <pad_checksum_prefix> - Decrypt message\n", program_name); printf(" %s decrypt <pad_checksum_prefix> [message] - Decrypt message\n", program_name);
printf(" %s list - List available pads\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("\nSize examples: 1GB, 5TB, 512MB, 2048 (bytes)\n");
printf("Pad selection: Full chksum, prefix, or number from list\n"); printf("Pad selection: Full chksum, prefix, or number from list\n");
} }