example_persistence.c (6430B)
1 /* 2 * Example: Saving and Loading Encrypted Data 3 * 4 * Demonstrates how to: 5 * 1. Encrypt data 6 * 2. Serialize it to bytes 7 * 3. Save to a file 8 * 4. Load from file after restart 9 * 5. Deserialize and decrypt 10 */ 11 12 #include "EasyCrypto.h" 13 #include "CSPRNG.h" 14 #include <stdio.h> 15 #include <string.h> 16 #include <fcntl.h> 17 #include <unistd.h> 18 19 /* Save bytes to file */ 20 int save_to_file(const char *filename, const uint8_t *data, size_t len) { 21 int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); 22 if (fd < 0) { 23 perror("Failed to open file for writing"); 24 return -1; 25 } 26 27 ssize_t written = write(fd, data, len); 28 close(fd); 29 30 if (written != (ssize_t)len) { 31 fprintf(stderr, "Failed to write all data to file\n"); 32 return -1; 33 } 34 35 return 0; 36 } 37 38 /* Load bytes from file */ 39 uint8_t* load_from_file(const char *filename, size_t *len) { 40 int fd = open(filename, O_RDONLY); 41 if (fd < 0) { 42 perror("Failed to open file for reading"); 43 return NULL; 44 } 45 46 /* Get file size */ 47 off_t file_size = lseek(fd, 0, SEEK_END); 48 if (file_size < 0) { 49 close(fd); 50 return NULL; 51 } 52 lseek(fd, 0, SEEK_SET); 53 54 /* Allocate buffer */ 55 uint8_t *buffer = malloc(file_size); 56 if (!buffer) { 57 close(fd); 58 return NULL; 59 } 60 61 /* Read file */ 62 ssize_t bytes_read = read(fd, buffer, file_size); 63 close(fd); 64 65 if (bytes_read != file_size) { 66 free(buffer); 67 return NULL; 68 } 69 70 *len = file_size; 71 return buffer; 72 } 73 74 int main(void) { 75 printf("╔════════════════════════════════════════════════════╗\n"); 76 printf("║ Encrypted Data Persistence Example ║\n"); 77 printf("╚════════════════════════════════════════════════════╝\n\n"); 78 79 /* Initialize CSPRNG */ 80 csprng_global_init(); 81 82 /* Generate encryption key */ 83 uint8_t key[32]; 84 random_bytes(key, 32); 85 86 printf("Step 1: Generate encryption key\n"); 87 printf("Key: "); 88 for (int i = 0; i < 16; i++) printf("%02x", key[i]); 89 printf("...\n\n"); 90 91 /* Data to encrypt */ 92 const char *secret_message = "This is confidential data that needs to survive a reboot!"; 93 printf("Step 2: Original message\n"); 94 printf("\"%s\"\n\n", secret_message); 95 96 /* Encrypt the data */ 97 printf("Step 3: Encrypt with Twofish-256-GCM\n"); 98 size_t encrypted_len; 99 void *encrypted = ENCRYPT_TWOFISH(key, (uint8_t*)secret_message, strlen(secret_message), &encrypted_len); 100 if (!encrypted) { 101 fprintf(stderr, "✗ Encryption failed\n"); 102 return 1; 103 } 104 printf("✓ Encrypted successfully\n"); 105 printf(" Format: [Nonce(12)][Tag(16)][Ciphertext(var)]\n"); 106 printf(" Total length: %zu bytes\n", encrypted_len); 107 printf(" Breakdown:\n"); 108 printf(" - Nonce: 12 bytes\n"); 109 printf(" - Tag: 16 bytes\n"); 110 printf(" - Ciphertext: %zu bytes\n\n", encrypted_len - 28); 111 112 /* Save to file */ 113 printf("Step 4: Save to file 'encrypted_data.bin'\n"); 114 if (save_to_file("encrypted_data.bin", encrypted, encrypted_len) != 0) { 115 fprintf(stderr, "✗ Failed to save to file\n"); 116 free(encrypted); 117 return 1; 118 } 119 printf("✓ Saved %zu bytes to encrypted_data.bin\n", encrypted_len); 120 printf(" First 32 bytes: "); 121 for (size_t i = 0; i < 32 && i < encrypted_len; i++) { 122 printf("%02x", ((uint8_t*)encrypted)[i]); 123 } 124 printf("...\n\n"); 125 126 /* Clean up */ 127 free(encrypted); 128 129 printf("════════════════════════════════════════════════════\n"); 130 printf("SIMULATING RESTART - All memory is cleared\n"); 131 printf("════════════════════════════════════════════════════\n\n"); 132 133 /* Load from file */ 134 printf("Step 5: Load from file after 'restart'\n"); 135 size_t loaded_len; 136 uint8_t *loaded = load_from_file("encrypted_data.bin", &loaded_len); 137 if (!loaded) { 138 fprintf(stderr, "✗ Failed to load from file\n"); 139 return 1; 140 } 141 printf("✓ Loaded %zu bytes from encrypted_data.bin\n", loaded_len); 142 printf(" Format: [Nonce(12)][Tag(16)][Ciphertext(%zu)]\n", loaded_len - 28); 143 printf(" First 32 bytes: "); 144 for (size_t i = 0; i < 32 && i < loaded_len; i++) { 145 printf("%02x", loaded[i]); 146 } 147 printf("...\n\n"); 148 149 /* Decrypt */ 150 printf("Step 6: Decrypt using the same key\n"); 151 size_t decrypted_len; 152 void *decrypted = DECRYPT_TWOFISH(key, loaded, loaded_len, &decrypted_len); 153 free(loaded); 154 155 if (!decrypted) { 156 fprintf(stderr, "✗ Decryption failed\n"); 157 return 1; 158 } 159 160 printf("✓ Decrypted successfully\n"); 161 printf(" Recovered message: \""); 162 fwrite(decrypted, 1, decrypted_len, stdout); 163 printf("\"\n\n"); 164 165 /* Verify */ 166 if (decrypted_len == strlen(secret_message) && 167 memcmp(decrypted, secret_message, decrypted_len) == 0) { 168 printf("✓ SUCCESS! Message survived the 'restart'\n\n"); 169 } else { 170 printf("✗ FAILED! Message was corrupted\n\n"); 171 } 172 173 free(decrypted); 174 175 /* Clean up */ 176 unlink("encrypted_data.bin"); 177 178 printf("════════════════════════════════════════════════════\n"); 179 printf("Key Points:\n"); 180 printf("════════════════════════════════════════════════════\n"); 181 printf("• ENCRYPT_TWOFISH returns void* with [Nonce][Tag][Ciphertext]\n"); 182 printf("• Format: [Nonce(12)][Tag(16)][Ciphertext(var)]\n"); 183 printf("• NO metadata - algorithm/lengths tracked externally\n"); 184 printf("• Direct to bytes - no serialization needed\n"); 185 printf("• Save bytes directly to disk/database/network\n"); 186 printf("• DECRYPT_TWOFISH reads the same format\n"); 187 printf("• Simple API: just encrypt, save, load, decrypt\n\n"); 188 189 /* Zero sensitive data */ 190 memset(key, 0, 32); 191 192 return 0; 193 }