diff options
| author | @syxhe <https://t.me/syxhe> | 2025-01-21 17:01:03 -0600 |
|---|---|---|
| committer | @syxhe <https://t.me/syxhe> | 2025-01-21 17:01:03 -0600 |
| commit | 5d3068832c6094cf3b3ffce89d2398134e939b1f (patch) | |
| tree | f23dc5597a1bfe76b2748f6762d09ff97f05141f /src/encryption.c | |
| parent | b15ffbc1e51f913d6ab1cfa345a06eecfc098405 (diff) | |
Write some sample code to encrypt a file via password
Diffstat (limited to 'src/encryption.c')
| -rw-r--r-- | src/encryption.c | 96 |
1 files changed, 92 insertions, 4 deletions
diff --git a/src/encryption.c b/src/encryption.c index 692b46a..100b50f 100644 --- a/src/encryption.c +++ b/src/encryption.c | |||
| @@ -179,7 +179,7 @@ int main(void) { | |||
| 179 | free(password); | 179 | free(password); |
| 180 | //*/// | 180 | //*/// |
| 181 | 181 | ||
| 182 | //*// Example code for generating a password, derriving a secret key from it, and storing things properly | 182 | /*// Example code for generating a password, derriving a secret key from it, and storing things properly |
| 183 | 183 | ||
| 184 | // Initialization | 184 | // Initialization |
| 185 | checksodium(); | 185 | checksodium(); |
| @@ -195,9 +195,9 @@ int main(void) { | |||
| 195 | // Store the password | 195 | // Store the password |
| 196 | if(crypto_pwhash_str(hpass, pass, strlen(pass) + 1, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0) | 196 | if(crypto_pwhash_str(hpass, pass, strlen(pass) + 1, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0) |
| 197 | error(1, errno, "Couldn't generate password, quitting..."); | 197 | error(1, errno, "Couldn't generate password, quitting..."); |
| 198 | /* Don't know if I want to use MODERATE or SENSITIVE for this. SENSITIVE takes a little bit on my laptop, which honestly | 198 | // Don't know if I want to use MODERATE or SENSITIVE for this. SENSITIVE takes a little bit on my laptop, which honestly |
| 199 | // shouldn't be a problem, but it annoys me. MODERATE is quick and snappy, or at least quick enough that the slowdown is | 199 | // shouldn't be a problem, but it annoys me. MODERATE is quick and snappy, or at least quick enough that the slowdown is |
| 200 | // barely noticable. I might do MODERATE for testing and SENSITIVE for release */ | 200 | // barely noticable. I might do MODERATE for testing and SENSITIVE for release |
| 201 | 201 | ||
| 202 | sodium_munlock(pass, strlen(pass) + 1); | 202 | sodium_munlock(pass, strlen(pass) + 1); |
| 203 | free(pass); | 203 | free(pass); |
| @@ -206,7 +206,7 @@ int main(void) { | |||
| 206 | 206 | ||
| 207 | // Check if the password from the user is correct | 207 | // Check if the password from the user is correct |
| 208 | char *uin = NULL; int size = -1; | 208 | char *uin = NULL; int size = -1; |
| 209 | if((size = readwholebuffer(&uin, 20, STDIN_FILENO)) < 0) | 209 | if((size = readwholebuffer(&uin, 1, STDIN_FILENO)) < 0) |
| 210 | error(1, errno, "Could not read from stdin"); | 210 | error(1, errno, "Could not read from stdin"); |
| 211 | sodium_mlock(uin, size); | 211 | sodium_mlock(uin, size); |
| 212 | 212 | ||
| @@ -218,6 +218,94 @@ int main(void) { | |||
| 218 | 218 | ||
| 219 | //*/// | 219 | //*/// |
| 220 | 220 | ||
| 221 | //*// Example code for generating a key from a password and encrypting a test file | ||
| 222 | |||
| 223 | const char *dir = ".", *fname = "toBeEncrypted.test.txt", *pass = "this is a password"; | ||
| 224 | char *path = NULL, *message = NULL, *efname = NULL; | ||
| 225 | int fd = -1; | ||
| 226 | |||
| 227 | // Message is just going to be a bunch of words from the dictionary | ||
| 228 | checksodium(); | ||
| 229 | if(genpassword(&message, 1000) < 0) | ||
| 230 | error(1, errno, "Could not generate message to be encrypted"); | ||
| 231 | if(!message) | ||
| 232 | abort(); | ||
| 233 | |||
| 234 | // Get the temp file and write the message into it | ||
| 235 | if((fd = maketmp(dir)) < 0) | ||
| 236 | error(1, errno, "Could not make temp file to write to"); | ||
| 237 | |||
| 238 | // Write to the file and link it into the system | ||
| 239 | remove(fname); // Make sure the new file can be linked into | ||
| 240 | write(fd, message, strlen(message)); | ||
| 241 | asprintf(&path, "/proc/self/fd/%d", fd); | ||
| 242 | if(!path) | ||
| 243 | abort(); | ||
| 244 | linkat(AT_FDCWD, path, AT_FDCWD, fname, AT_SYMLINK_FOLLOW); | ||
| 245 | |||
| 246 | free(path); | ||
| 247 | free(message); | ||
| 248 | close(fd); | ||
| 249 | |||
| 250 | |||
| 251 | // Time for encryption | ||
| 252 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | ||
| 253 | unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]; | ||
| 254 | crypto_secretstream_xchacha20poly1305_state state; | ||
| 255 | unsigned char salt[crypto_pwhash_SALTBYTES]; | ||
| 256 | |||
| 257 | // Generate a salt for derriving the key | ||
| 258 | randombytes_buf(salt, sizeof(salt)); | ||
| 259 | |||
| 260 | // Derrive the key from the password | ||
| 261 | if(crypto_pwhash(key, sizeof(key), pass, strlen(pass), salt, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE, crypto_pwhash_ALG_DEFAULT) != 0) | ||
| 262 | error(1, ENOMEM, "Not enough memory to generate a key"); | ||
| 263 | |||
| 264 | // Initialize the encryption stream's state | ||
| 265 | crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); | ||
| 266 | |||
| 267 | |||
| 268 | // Deal with getting the file | ||
| 269 | if((fd = open(fname, O_RDONLY)) < 0) | ||
| 270 | error(1, errno, "Could not open test file to encrypt"); | ||
| 271 | int tfd = -1; | ||
| 272 | if((tfd = maketmp(dir)) < 0) // Only because linking temp files is being annoying | ||
| 273 | error(1, errno, "Could not open temp file for encryption"); | ||
| 274 | |||
| 275 | struct stat sb; | ||
| 276 | if(fstat(fd, &sb) < 0) | ||
| 277 | error(1, errno, "stat() error"); | ||
| 278 | |||
| 279 | // Read chunks of the file, encrypt them, then write them into the tmp file | ||
| 280 | ssize_t bytesread = -1; | ||
| 281 | unsigned char *buf = xcalloc(sb.st_blksize + 1, sizeof(*buf)); | ||
| 282 | unsigned char *cbuf = xcalloc((sb.st_blksize + 1) + crypto_secretstream_xchacha20poly1305_ABYTES, sizeof(*buf)); | ||
| 283 | while((bytesread = read(fd, buf, sb.st_blksize)) >= 0) { | ||
| 284 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, NULL, buf, bytesread, NULL, 0, (bytesread > 0) ? 0 : crypto_secretstream_xchacha20poly1305_TAG_FINAL); | ||
| 285 | if(writewholebuffer(tfd, cbuf, bytesread) < 0) | ||
| 286 | error(1, errno, "write() error"); | ||
| 287 | |||
| 288 | if(bytesread == 0) | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | if(bytesread < 0) | ||
| 292 | error(1, errno, "read() error"); | ||
| 293 | |||
| 294 | close(fd); | ||
| 295 | |||
| 296 | asprintf(&efname, "%s.enc", fname); | ||
| 297 | asprintf(&path, "/proc/self/fd/%d", tfd); | ||
| 298 | if(!path || !efname) | ||
| 299 | abort(); | ||
| 300 | remove(efname); // Make sure an old version isn't sticking around | ||
| 301 | linkat(AT_FDCWD, path, AT_FDCWD, efname, AT_SYMLINK_FOLLOW); | ||
| 302 | |||
| 303 | close(tfd); | ||
| 304 | free(path); | ||
| 305 | free(efname); | ||
| 306 | |||
| 307 | //*/// | ||
| 308 | |||
| 221 | return 0; | 309 | return 0; |
| 222 | } | 310 | } |
| 223 | 311 | ||
