Compare commits

...

3 Commits

4 changed files with 8951 additions and 85 deletions

View File

@@ -164,11 +164,9 @@ Offset | Size | Field | Description
4 | 2 | Version | Format version (currently 1) 4 | 2 | Version | Format version (currently 1)
6 | 32 | Pad Checksum | Binary pad checksum (32 bytes) 6 | 32 | Pad Checksum | Binary pad checksum (32 bytes)
38 | 8 | Pad Offset | Offset in pad file (uint64_t) 38 | 8 | Pad Offset | Offset in pad file (uint64_t)
46 | 2 | Filename Length | Original filename length (uint16_t) 46 | 4 | File Mode | Original file permissions (uint32_t)
48 | var | Original Filename | Original filename string 50 | 8 | File Size | Original file size (uint64_t)
var | 4 | File Mode | Original file permissions (uint32_t) 58 | var | Encrypted Data | XOR-encrypted file contents
var | 8 | File Size | Original file size (uint64_t)
var | var | Encrypted Data | XOR-encrypted file contents
``` ```
### .otp.asc File Format (ASCII Armored) ### .otp.asc File Format (ASCII Armored)
@@ -185,7 +183,7 @@ Pad-Offset: <decimal-offset-value>
-----END OTP MESSAGE----- -----END OTP MESSAGE-----
``` ```
**Note:** ASCII armored files lose original filename and permission metadata. **Note:** ASCII armored files do not preserve original file permissions metadata.
## Usage Examples ## Usage Examples

Binary file not shown.

104
otp.c
View File

@@ -151,6 +151,14 @@ int interactive_mode(void) {
} }
int command_line_mode(int argc, char* argv[]) { int command_line_mode(int argc, char* argv[]) {
// Check for help flags first
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0 ||
strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0 ||
strcmp(argv[1], "help") == 0) {
print_usage(argv[0]);
return 0;
}
if (strcmp(argv[1], "generate") == 0 || strcmp(argv[1], "-g") == 0) { if (strcmp(argv[1], "generate") == 0 || strcmp(argv[1], "-g") == 0) {
if (argc != 3) { if (argc != 3) {
printf("Usage: %s generate|-g <size>\n", argv[0]); printf("Usage: %s generate|-g <size>\n", argv[0]);
@@ -374,31 +382,7 @@ char* find_pad_by_prefix(const char* prefix) {
char* matches[100]; // Store up to 100 matches char* matches[100]; // Store up to 100 matches
int match_count = 0; int match_count = 0;
// Check if it's a number (for interactive menu selection) // Always try hex prefix matching first
// Only treat as number if it's a single digit (1-9) to avoid conflicts with hex prefixes
char* endptr;
int selection = strtol(prefix, &endptr, 10);
if (*endptr == '\0' && selection > 0 && selection <= 9 && strlen(prefix) == 1) {
// It's a number, find the nth pad
int current = 0;
rewinddir(dir);
while ((entry = readdir(dir)) != NULL && match_count == 0) {
// Skip . and .. entries, and only process .pad files
if (entry->d_name[0] == '.') continue;
if (!strstr(entry->d_name, ".pad")) continue;
if (strlen(entry->d_name) != 68) continue; // 64 char chksum + ".pad"
current++;
if (current == selection) {
matches[match_count] = malloc(65);
strncpy(matches[match_count], entry->d_name, 64);
matches[match_count][64] = '\0';
match_count = 1;
break;
}
}
} else {
// Find pads that start with the prefix
size_t prefix_len = strlen(prefix); size_t prefix_len = strlen(prefix);
while ((entry = readdir(dir)) != NULL && match_count < 100) { while ((entry = readdir(dir)) != NULL && match_count < 100) {
// Skip . and .. entries, and only process .pad files // Skip . and .. entries, and only process .pad files
@@ -414,6 +398,31 @@ char* find_pad_by_prefix(const char* prefix) {
match_count++; match_count++;
} }
} }
// If no hex prefix matches and it looks like a small number, try number selection
if (match_count == 0) {
char* endptr;
int selection = strtol(prefix, &endptr, 10);
if (*endptr == '\0' && selection > 0 && selection <= 100) {
// It's a number, find the nth pad
int current = 0;
rewinddir(dir);
while ((entry = readdir(dir)) != NULL) {
// Skip . and .. entries, and only process .pad files
if (entry->d_name[0] == '.') continue;
if (!strstr(entry->d_name, ".pad")) continue;
if (strlen(entry->d_name) != 68) continue; // 64 char chksum + ".pad"
current++;
if (current == selection) {
matches[match_count] = malloc(65);
strncpy(matches[match_count], entry->d_name, 64);
matches[match_count][64] = '\0';
match_count = 1;
break;
}
}
}
} }
closedir(dir); closedir(dir);
@@ -1445,16 +1454,6 @@ int encrypt_file(const char* pad_identifier, const char* input_file, const char*
// Pad offset: 8 bytes // Pad offset: 8 bytes
fwrite(&current_offset, sizeof(uint64_t), 1, output_fp); fwrite(&current_offset, sizeof(uint64_t), 1, output_fp);
// Original filename length and name
const char* base_filename = strrchr(input_file, '/');
if (base_filename) {
base_filename++; // Skip the '/'
} else {
base_filename = input_file;
}
uint16_t filename_len = strlen(base_filename);
fwrite(&filename_len, sizeof(uint16_t), 1, output_fp);
fwrite(base_filename, 1, filename_len, output_fp);
// File mode: 4 bytes // File mode: 4 bytes
uint32_t file_mode = input_stat.st_mode; uint32_t file_mode = input_stat.st_mode;
@@ -1527,7 +1526,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
uint16_t version; uint16_t version;
unsigned char pad_chksum_bin[32]; unsigned char pad_chksum_bin[32];
uint64_t pad_offset; uint64_t pad_offset;
uint16_t filename_len;
uint32_t file_mode; uint32_t file_mode;
uint64_t file_size; uint64_t file_size;
@@ -1535,7 +1533,8 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
fread(&version, sizeof(uint16_t), 1, input_fp) != 1 || fread(&version, sizeof(uint16_t), 1, input_fp) != 1 ||
fread(pad_chksum_bin, 1, 32, input_fp) != 32 || fread(pad_chksum_bin, 1, 32, input_fp) != 32 ||
fread(&pad_offset, sizeof(uint64_t), 1, input_fp) != 1 || fread(&pad_offset, sizeof(uint64_t), 1, input_fp) != 1 ||
fread(&filename_len, sizeof(uint16_t), 1, input_fp) != 1) { fread(&file_mode, sizeof(uint32_t), 1, input_fp) != 1 ||
fread(&file_size, sizeof(uint64_t), 1, input_fp) != 1) {
printf("Error: Cannot read binary header\n"); printf("Error: Cannot read binary header\n");
fclose(input_fp); fclose(input_fp);
return 1; return 1;
@@ -1547,25 +1546,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
return 1; return 1;
} }
// Read original filename
char* original_filename = malloc(filename_len + 1);
if (fread(original_filename, 1, filename_len, input_fp) != filename_len) {
printf("Error: Cannot read original filename\n");
free(original_filename);
fclose(input_fp);
return 1;
}
original_filename[filename_len] = '\0';
// Read remaining header
if (fread(&file_mode, sizeof(uint32_t), 1, input_fp) != 1 ||
fread(&file_size, sizeof(uint64_t), 1, input_fp) != 1) {
printf("Error: Cannot read file metadata\n");
free(original_filename);
fclose(input_fp);
return 1;
}
// Convert binary checksum to hex // Convert binary checksum to hex
char pad_chksum_hex[65]; char pad_chksum_hex[65];
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
@@ -1574,7 +1554,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
pad_chksum_hex[64] = '\0'; pad_chksum_hex[64] = '\0';
printf("Decrypting binary file...\n"); printf("Decrypting binary file...\n");
printf("Original filename: %s\n", original_filename);
printf("File size: %lu bytes\n", file_size); printf("File size: %lu bytes\n", file_size);
// Check if we have the required pad // Check if we have the required pad
@@ -1586,7 +1565,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
printf("Error: Required pad not found: %s\n", pad_chksum_hex); printf("Error: Required pad not found: %s\n", pad_chksum_hex);
printf("Available pads:\n"); printf("Available pads:\n");
list_available_pads(); list_available_pads();
free(original_filename);
fclose(input_fp); fclose(input_fp);
return 1; return 1;
} }
@@ -1594,8 +1572,7 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
// Determine output filename // Determine output filename
char default_output[512]; char default_output[512];
if (output_file == NULL) { if (output_file == NULL) {
strncpy(default_output, original_filename, sizeof(default_output) - 1); snprintf(default_output, sizeof(default_output), "decrypted.bin");
default_output[sizeof(default_output) - 1] = '\0';
output_file = default_output; output_file = default_output;
} }
@@ -1603,7 +1580,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
unsigned char* encrypted_data = malloc(file_size); unsigned char* encrypted_data = malloc(file_size);
if (fread(encrypted_data, 1, file_size, input_fp) != file_size) { if (fread(encrypted_data, 1, file_size, input_fp) != file_size) {
printf("Error: Cannot read encrypted data\n"); printf("Error: Cannot read encrypted data\n");
free(original_filename);
free(encrypted_data); free(encrypted_data);
fclose(input_fp); fclose(input_fp);
return 1; return 1;
@@ -1614,14 +1590,12 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
FILE* pad_file = fopen(pad_path, "rb"); FILE* pad_file = fopen(pad_path, "rb");
if (!pad_file) { if (!pad_file) {
printf("Error: Cannot open pad file\n"); printf("Error: Cannot open pad file\n");
free(original_filename);
free(encrypted_data); free(encrypted_data);
return 1; return 1;
} }
if (fseek(pad_file, pad_offset, SEEK_SET) != 0) { if (fseek(pad_file, pad_offset, SEEK_SET) != 0) {
printf("Error: Cannot seek to offset in pad file\n"); printf("Error: Cannot seek to offset in pad file\n");
free(original_filename);
free(encrypted_data); free(encrypted_data);
fclose(pad_file); fclose(pad_file);
return 1; return 1;
@@ -1630,7 +1604,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
unsigned char* pad_data = malloc(file_size); unsigned char* pad_data = malloc(file_size);
if (fread(pad_data, 1, file_size, pad_file) != file_size) { if (fread(pad_data, 1, file_size, pad_file) != file_size) {
printf("Error: Cannot read pad data\n"); printf("Error: Cannot read pad data\n");
free(original_filename);
free(encrypted_data); free(encrypted_data);
free(pad_data); free(pad_data);
fclose(pad_file); fclose(pad_file);
@@ -1647,7 +1620,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
FILE* output_fp = fopen(output_file, "wb"); FILE* output_fp = fopen(output_file, "wb");
if (!output_fp) { if (!output_fp) {
printf("Error: Cannot create output file %s\n", output_file); printf("Error: Cannot create output file %s\n", output_file);
free(original_filename);
free(encrypted_data); free(encrypted_data);
free(pad_data); free(pad_data);
return 1; return 1;
@@ -1655,7 +1627,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
if (fwrite(encrypted_data, 1, file_size, output_fp) != file_size) { if (fwrite(encrypted_data, 1, file_size, output_fp) != file_size) {
printf("Error: Cannot write decrypted data\n"); printf("Error: Cannot write decrypted data\n");
free(original_filename);
free(encrypted_data); free(encrypted_data);
free(pad_data); free(pad_data);
fclose(output_fp); fclose(output_fp);
@@ -1672,7 +1643,6 @@ int decrypt_binary_file(FILE* input_fp, const char* output_file) {
printf("Restored permissions and metadata\n"); printf("Restored permissions and metadata\n");
// Cleanup // Cleanup
free(original_filename);
free(encrypted_data); free(encrypted_data);
free(pad_data); free(pad_data);

8898
toc.txt Executable file

File diff suppressed because it is too large Load Diff