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/
Gemini.md

View File

@@ -200,3 +200,4 @@ When contributing:
2. For major features, consider manually creating minor version tags
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_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
increment_version() {
print_status "Incrementing version..."
@@ -57,16 +74,18 @@ increment_version() {
print_warning "Failed to stage changes (maybe not a git repository)"
fi
# Prompt for commit message
# Handle commit message - use global variable if set, otherwise prompt
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="Version $NEW_VERSION - Automatic version increment"
COMMIT_MESSAGE="Automatic version increment"
fi
# Commit changes with user-provided message
@@ -239,7 +258,10 @@ case "${1:-build}" in
;;
*)
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 "Commands:"
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 " uninstall - Remove from system"
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
;;
esac

104
otp.c
View File

@@ -50,8 +50,8 @@ int command_line_mode(int argc, char* argv[]);
// Core functions
int generate_pad(uint64_t size_bytes, int show_progress);
int generate_pad_with_entropy(uint64_t size_bytes, int show_progress, int use_keyboard_entropy);
int encrypt_text(const char* pad_identifier);
int decrypt_text(const char* pad_identifier);
int encrypt_text(const char* pad_identifier, const char* input_text);
int decrypt_text(const char* pad_identifier, const char* encrypted_message);
// Keyboard entropy functions
int setup_raw_terminal(struct termios* original_termios);
@@ -161,18 +161,22 @@ int command_line_mode(int argc, char* argv[]) {
return generate_pad_with_entropy(size, 1, 0); // No keyboard entropy for command line
}
else if (strcmp(argv[1], "encrypt") == 0) {
if (argc != 3) {
printf("Usage: %s encrypt <pad_chksum_or_prefix>\n", argv[0]);
if (argc < 3 || argc > 4) {
printf("Usage: %s encrypt <pad_chksum_or_prefix> [text_to_encrypt]\n", argv[0]);
return 1;
}
return encrypt_text(argv[2]);
// Pass text if provided, otherwise NULL for interactive mode
const char* text = (argc == 4) ? argv[3] : NULL;
return encrypt_text(argv[2], text);
}
else if (strcmp(argv[1], "decrypt") == 0) {
if (argc != 3) {
printf("Usage: %s decrypt <pad_chksum_or_prefix>\n", argv[0]);
if (argc < 3 || argc > 4) {
printf("Usage: %s decrypt <pad_chksum_or_prefix> [encrypted_message]\n", argv[0]);
return 1;
}
return decrypt_text(argv[2]);
// Pass message if provided, otherwise NULL for interactive mode
const char* message = (argc == 4) ? argv[3] : NULL;
return decrypt_text(argv[2], message);
}
else if (strcmp(argv[1], "list") == 0) {
return list_available_pads();
@@ -250,12 +254,12 @@ int handle_encrypt_menu(void) {
}
input[strcspn(input, "\n")] = 0;
return encrypt_text(input);
return encrypt_text(input, NULL); // NULL for interactive mode
}
int handle_decrypt_menu(void) {
printf("\n=== Decrypt Message ===\n");
return decrypt_text(NULL); // No pad selection needed - chksum comes from message
return decrypt_text(NULL, NULL); // No pad selection needed - chksum comes from message
}
uint64_t parse_size_string(const char* size_str) {
@@ -797,13 +801,13 @@ int generate_pad_with_entropy(uint64_t size_bytes, int display_progress, int use
return 0;
}
int encrypt_text(const char* pad_identifier) {
int encrypt_text(const char* pad_identifier, const char* input_text) {
char* pad_chksum = find_pad_by_prefix(pad_identifier);
if (!pad_chksum) {
return 1;
}
char input_text[MAX_INPUT_SIZE];
char text_buffer[MAX_INPUT_SIZE];
char chksum_hex[MAX_HASH_LENGTH];
uint64_t current_offset;
@@ -841,23 +845,30 @@ int encrypt_text(const char* pad_identifier) {
return 1;
}
// Get input text from user
// Get input text - either from parameter or user input
if (input_text != NULL) {
// Use provided text
strncpy(text_buffer, input_text, sizeof(text_buffer) - 1);
text_buffer[sizeof(text_buffer) - 1] = '\0';
} else {
// Get input text from user (interactive mode)
printf("Enter text to encrypt: ");
fflush(stdout);
if (fgets(input_text, sizeof(input_text), stdin) == NULL) {
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 input_len = strlen(input_text);
if (input_len > 0 && input_text[input_len - 1] == '\n') {
input_text[input_len - 1] = '\0';
input_len--;
size_t len = strlen(text_buffer);
if (len > 0 && text_buffer[len - 1] == '\n') {
text_buffer[len - 1] = '\0';
}
}
size_t input_len = strlen(text_buffer);
if (input_len == 0) {
printf("Error: No input provided\n");
free(pad_chksum);
@@ -908,7 +919,7 @@ int encrypt_text(const char* pad_identifier) {
// XOR encrypt the input
unsigned char* ciphertext = malloc(input_len);
for (size_t i = 0; i < input_len; i++) {
ciphertext[i] = input_text[i] ^ pad_data[i];
ciphertext[i] = text_buffer[i] ^ pad_data[i];
}
// Encode as base64
@@ -943,7 +954,7 @@ int encrypt_text(const char* pad_identifier) {
return 0;
}
int decrypt_text(const char* pad_identifier) {
int decrypt_text(const char* pad_identifier, const char* encrypted_message) {
// For command line mode, pad_identifier is ignored - we'll get the chksum from the message
(void)pad_identifier; // Suppress unused parameter warning
@@ -954,6 +965,44 @@ int decrypt_text(const char* pad_identifier) {
char base64_data[MAX_INPUT_SIZE * 2] = {0};
int in_data_section = 0;
if (encrypted_message != NULL) {
// Parse provided encrypted message
char *message_copy = strdup(encrypted_message);
char *line_ptr = strtok(message_copy, "\n");
int found_begin = 0;
while (line_ptr != NULL) {
if (strcmp(line_ptr, "-----BEGIN OTP MESSAGE-----") == 0) {
found_begin = 1;
}
else if (strcmp(line_ptr, "-----END OTP MESSAGE-----") == 0) {
break;
}
else if (found_begin) {
if (strncmp(line_ptr, "Pad-ChkSum: ", 12) == 0) {
strncpy(stored_chksum, line_ptr + 12, 64);
stored_chksum[64] = '\0';
}
else if (strncmp(line_ptr, "Pad-Offset: ", 12) == 0) {
pad_offset = strtoull(line_ptr + 12, NULL, 10);
}
else if (strlen(line_ptr) == 0) {
in_data_section = 1;
}
else if (in_data_section) {
strncat(base64_data, line_ptr, sizeof(base64_data) - strlen(base64_data) - 1);
}
}
line_ptr = strtok(NULL, "\n");
}
free(message_copy);
if (!found_begin) {
printf("Error: Invalid message format - missing BEGIN header\n");
return 1;
}
} else {
// Interactive mode - read from stdin
printf("Enter encrypted message (paste the full ASCII armor block):\n");
// Read the ASCII armor format
@@ -991,6 +1040,12 @@ int decrypt_text(const char* pad_identifier) {
printf("Error: Invalid message format - missing BEGIN header\n");
return 1;
}
}
if (!found_begin) {
printf("Error: Invalid message format - missing BEGIN header\n");
return 1;
}
// Now we have the pad chksum from the message, construct filename
char pad_path[MAX_HASH_LENGTH + 20];
@@ -1347,9 +1402,14 @@ void print_usage(const char* program_name) {
printf("Usage:\n");
printf(" %s - Interactive mode\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 decrypt <pad_checksum_prefix> - Decrypt message\n", program_name);
printf(" %s encrypt <pad_checksum_prefix> [text] - Encrypt text\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("\nExamples:\n");
printf(" %s encrypt 1a2b3c \"Hello world\" - Encrypt inline text\n", program_name);
printf(" %s encrypt 1a2b3c - Encrypt interactively\n", program_name);
printf(" %s decrypt 1a2b3c \"-----BEGIN OTP...\" - Decrypt inline message\n", program_name);
printf(" %s decrypt 1a2b3c - Decrypt interactively\n", program_name);
printf("\nSize examples: 1GB, 5TB, 512MB, 2048 (bytes)\n");
printf("Pad selection: Full chksum, prefix, or number from list\n");
}