Compare commits

...

3 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
8e1fcdb108 Version v0.2.12 - Edited build.sh 2025-08-10 09:53:24 -04:00
4 changed files with 166 additions and 64 deletions

1
.gitignore vendored
View File

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

View File

@@ -199,3 +199,5 @@ When contributing:
1. The version will automatically increment on builds 1. The version will automatically increment on builds
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
# 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,8 +74,22 @@ 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
# Commit changes with version message # Handle commit message - use global variable if set, otherwise prompt
if git commit -m "Version $NEW_VERSION - Automatic version increment" 2>/dev/null; then if [[ -z "$COMMIT_MESSAGE" ]]; then
echo ""
print_status "Please enter a meaningful commit message for version $NEW_VERSION:"
echo -n "> "
read -r COMMIT_MESSAGE
fi
# Check if user provided a message
if [[ -z "$COMMIT_MESSAGE" ]]; then
print_warning "No commit message provided. Using default message."
COMMIT_MESSAGE="Automatic version increment"
fi
# Commit changes with user-provided message
if git commit -m "Version $NEW_VERSION - $COMMIT_MESSAGE" 2>/dev/null; then
print_success "Committed changes for version $NEW_VERSION" print_success "Committed changes for version $NEW_VERSION"
else else
print_warning "Failed to commit changes (maybe no changes to commit or not a git repository)" print_warning "Failed to commit changes (maybe no changes to commit or not a git repository)"
@@ -227,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)"
@@ -236,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

182
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);
if (fgets(input_text, sizeof(input_text), stdin) == NULL) { text_buffer[sizeof(text_buffer) - 1] = '\0';
printf("Error: Failed to read input\n"); } else {
free(pad_chksum); // Get input text from user (interactive mode)
return 1; printf("Enter text to encrypt: ");
} fflush(stdout);
// Remove newline if present if (fgets(text_buffer, sizeof(text_buffer), stdin) == NULL) {
size_t input_len = strlen(input_text); printf("Error: Failed to read input\n");
if (input_len > 0 && input_text[input_len - 1] == '\n') { free(pad_chksum);
input_text[input_len - 1] = '\0'; return 1;
input_len--; }
// Remove newline if present
size_t len = strlen(text_buffer);
if (len > 0 && text_buffer[len - 1] == '\n') {
text_buffer[len - 1] = '\0';
}
} }
size_t input_len = strlen(text_buffer);
if (input_len == 0) { 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
// Read the ASCII armor format char *message_copy = strdup(encrypted_message);
int found_begin = 0; char *line_ptr = strtok(message_copy, "\n");
while (fgets(line, sizeof(line), stdin)) {
line[strcspn(line, "\n")] = 0;
if (strcmp(line, "-----BEGIN OTP MESSAGE-----") == 0) { int found_begin = 0;
found_begin = 1; while (line_ptr != NULL) {
continue; if (strcmp(line_ptr, "-----BEGIN OTP MESSAGE-----") == 0) {
found_begin = 1;
}
else if (strcmp(line_ptr, "-----END OTP MESSAGE-----") == 0) {
break;
}
else if (found_begin) {
if (strncmp(line_ptr, "Pad-ChkSum: ", 12) == 0) {
strncpy(stored_chksum, line_ptr + 12, 64);
stored_chksum[64] = '\0';
}
else if (strncmp(line_ptr, "Pad-Offset: ", 12) == 0) {
pad_offset = strtoull(line_ptr + 12, NULL, 10);
}
else if (strlen(line_ptr) == 0) {
in_data_section = 1;
}
else if (in_data_section) {
strncat(base64_data, line_ptr, sizeof(base64_data) - strlen(base64_data) - 1);
}
}
line_ptr = strtok(NULL, "\n");
}
free(message_copy);
if (!found_begin) {
printf("Error: Invalid message format - missing BEGIN header\n");
return 1;
}
} else {
// Interactive mode - read from stdin
printf("Enter encrypted message (paste the full ASCII armor block):\n");
// Read the ASCII armor format
int found_begin = 0;
while (fgets(line, sizeof(line), stdin)) {
line[strcspn(line, "\n")] = 0;
if (strcmp(line, "-----BEGIN OTP MESSAGE-----") == 0) {
found_begin = 1;
continue;
}
if (strcmp(line, "-----END OTP MESSAGE-----") == 0) {
break;
}
if (!found_begin) continue;
if (strncmp(line, "Pad-ChkSum: ", 12) == 0) {
strncpy(stored_chksum, line + 12, 64);
stored_chksum[64] = '\0';
}
else if (strncmp(line, "Pad-Offset: ", 12) == 0) {
pad_offset = strtoull(line + 12, NULL, 10);
}
else if (strlen(line) == 0) {
in_data_section = 1;
}
else if (in_data_section) {
strncat(base64_data, line, sizeof(base64_data) - strlen(base64_data) - 1);
}
} }
if (strcmp(line, "-----END OTP MESSAGE-----") == 0) { 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");
} }