diff options
| author | @syxhe <https://t.me/syxhe> | 2025-01-27 17:18:01 -0600 |
|---|---|---|
| committer | @syxhe <https://t.me/syxhe> | 2025-01-27 17:18:01 -0600 |
| commit | 7aab85b35f884344585101aedfbd3a922bdeeb19 (patch) | |
| tree | 9145ae31026e5650a7cab757fa9171ccbb0281cb | |
| parent | 47a1a3a803de74b2521720966318a8be23490e7c (diff) | |
Write encrypttotmp, fuck up decryption again
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | src/encryption.c | 155 | ||||
| -rw-r--r-- | src/encryption.h | 2 | ||||
| -rw-r--r-- | src/shared.h | 6 |
4 files changed, 161 insertions, 5 deletions
| @@ -3,4 +3,5 @@ encryption | |||
| 3 | a.out | 3 | a.out |
| 4 | bin/ | 4 | bin/ |
| 5 | *.o | 5 | *.o |
| 6 | *test* \ No newline at end of file | 6 | *test* |
| 7 | *.enc \ No newline at end of file | ||
diff --git a/src/encryption.c b/src/encryption.c index e4fed1f..8b0ac83 100644 --- a/src/encryption.c +++ b/src/encryption.c | |||
| @@ -83,12 +83,91 @@ int maketmp(const char * const dest) { | |||
| 83 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); | 83 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | int encrypttotmp(const char * const target, const char * const output, const char * const password, int chunksize) { | 86 | int encrypttotmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { |
| 87 | #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 87 | #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| 88 | checksodium(); | 88 | checksodium(); |
| 89 | #endif | 89 | #endif |
| 90 | 90 | ||
| 91 | 91 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | |
| 92 | crypto_secretstream_xchacha20poly1305_state state; | ||
| 93 | int fd = -1, tfd = -1; | ||
| 94 | |||
| 95 | // Open the target file | ||
| 96 | if((fd = open(target, O_RDONLY)) < 0) | ||
| 97 | return -1; | ||
| 98 | |||
| 99 | // Create a temp file for writing | ||
| 100 | char *targetdir = xdirname(output); | ||
| 101 | tfd = maketmp(targetdir); | ||
| 102 | free(targetdir); | ||
| 103 | if(tfd < 0) | ||
| 104 | return -2; | ||
| 105 | |||
| 106 | // Initialize crypto stuff | ||
| 107 | if(crypto_secretstream_xchacha20poly1305_init_push(&state, header, key) < 0) { | ||
| 108 | close(fd); | ||
| 109 | close(tfd); | ||
| 110 | return -3; | ||
| 111 | } | ||
| 112 | |||
| 113 | ssize_t bytesread = -1; | ||
| 114 | unsigned char *buf = malloc(CHUNK_SIZE + 1); | ||
| 115 | unsigned char *cbuf = malloc((CHUNK_SIZE + 1) + crypto_secretstream_xchacha20poly1305_ABYTES); | ||
| 116 | if(!buf || !cbuf) { | ||
| 117 | close(fd); | ||
| 118 | close(tfd); | ||
| 119 | if(buf) | ||
| 120 | free(buf); | ||
| 121 | if(cbuf) | ||
| 122 | free(cbuf); | ||
| 123 | |||
| 124 | return -4; | ||
| 125 | } | ||
| 126 | |||
| 127 | // Write the header to the temp file before encrypting anything | ||
| 128 | if(writewholebuffer(tfd, header, sizeof(header)) < 0) { | ||
| 129 | close(fd); | ||
| 130 | close(tfd); | ||
| 131 | free(buf); | ||
| 132 | free(cbuf); | ||
| 133 | return -5; | ||
| 134 | } | ||
| 135 | |||
| 136 | // Read a chunk at a time, encrypt it, then push it to the temp file | ||
| 137 | unsigned long long clen = 0; | ||
| 138 | while((bytesread = read(fd, buf, CHUNK_SIZE)) >= 0) { | ||
| 139 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, &clen, buf, bytesread, NULL, 0, (bytesread > 0) ? 0 : crypto_secretstream_xchacha20poly1305_TAG_FINAL); | ||
| 140 | if(writewholebuffer(tfd, cbuf, clen) < 0) { | ||
| 141 | close(fd); | ||
| 142 | close(tfd); | ||
| 143 | free(buf); | ||
| 144 | free(cbuf); | ||
| 145 | return -6; | ||
| 146 | } | ||
| 147 | |||
| 148 | if(bytesread == 0) | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | free(buf); | ||
| 152 | free(cbuf); | ||
| 153 | close(fd); | ||
| 154 | if(bytesread < 0) { | ||
| 155 | close(tfd); | ||
| 156 | return -7; | ||
| 157 | } | ||
| 158 | |||
| 159 | // Link the temp file into the system | ||
| 160 | char *path = NULL; | ||
| 161 | asprintf(&path, "/proc/self/fd/%d", tfd); | ||
| 162 | if(!path) { | ||
| 163 | close(tfd); | ||
| 164 | return -8; | ||
| 165 | } | ||
| 166 | remove(output); // Make sure an old version isn't sticking around | ||
| 167 | linkat(AT_FDCWD, path, AT_FDCWD, output, AT_SYMLINK_FOLLOW); | ||
| 168 | |||
| 169 | free(path); | ||
| 170 | close(tfd); | ||
| 92 | 171 | ||
| 93 | return 0; | 172 | return 0; |
| 94 | } | 173 | } |
| @@ -217,7 +296,7 @@ int main(void) { | |||
| 217 | 296 | ||
| 218 | //*/// | 297 | //*/// |
| 219 | 298 | ||
| 220 | /*// Example code for generating a key from a password and encrypting a test file | 299 | //*// Example code for generating a key from a password and encrypting a test file |
| 221 | 300 | ||
| 222 | const char *dir = ".", *fname = "toBeEncrypted.test.txt", *pass = "this is a password"; | 301 | const char *dir = ".", *fname = "toBeEncrypted.test.txt", *pass = "this is a password"; |
| 223 | char *path = NULL, *message = NULL, *efname = NULL; | 302 | char *path = NULL, *message = NULL, *efname = NULL; |
| @@ -273,9 +352,14 @@ int main(void) { | |||
| 273 | 352 | ||
| 274 | // Read chunks of the file, encrypt them, then write them into the tmp file | 353 | // Read chunks of the file, encrypt them, then write them into the tmp file |
| 275 | ssize_t bytesread = -1; | 354 | ssize_t bytesread = -1; |
| 276 | const int CHUNK_SIZE = 4096; | 355 | // const int CHUNK_SIZE = 4096; |
| 277 | unsigned char *buf = xcalloc(CHUNK_SIZE + 1, sizeof(*buf)); | 356 | unsigned char *buf = xcalloc(CHUNK_SIZE + 1, sizeof(*buf)); |
| 278 | unsigned char *cbuf = xcalloc((CHUNK_SIZE + 1) + crypto_secretstream_xchacha20poly1305_ABYTES, sizeof(*cbuf)); | 357 | unsigned char *cbuf = xcalloc((CHUNK_SIZE + 1) + crypto_secretstream_xchacha20poly1305_ABYTES, sizeof(*cbuf)); |
| 358 | |||
| 359 | // TODO: WRITE HEADER TO FILE SO IT'S A VALID STREAM AND NOT BULLSHIT LIKE IT IS NOW | ||
| 360 | if(writewholebuffer(tfd, header, sizeof(header)) < 0) | ||
| 361 | error(1, errno, "Could not write header to file"); | ||
| 362 | |||
| 279 | while((bytesread = read(fd, buf, CHUNK_SIZE)) >= 0) { | 363 | while((bytesread = read(fd, buf, CHUNK_SIZE)) >= 0) { |
| 280 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, NULL, buf, bytesread, NULL, 0, (bytesread > 0) ? 0 : crypto_secretstream_xchacha20poly1305_TAG_FINAL); | 364 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, NULL, buf, bytesread, NULL, 0, (bytesread > 0) ? 0 : crypto_secretstream_xchacha20poly1305_TAG_FINAL); |
| 281 | if(writewholebuffer(tfd, cbuf, bytesread) < 0) | 365 | if(writewholebuffer(tfd, cbuf, bytesread) < 0) |
| @@ -303,6 +387,69 @@ int main(void) { | |||
| 303 | 387 | ||
| 304 | //*/// | 388 | //*/// |
| 305 | 389 | ||
| 390 | //*// Sample code to decrypt a file using a password-generated key | ||
| 391 | // Hint - Make sure the previous code block is also uncommented, or this will not work | ||
| 392 | |||
| 393 | char *dfname = NULL; | ||
| 394 | asprintf(&dfname, "%s.dec", efname); | ||
| 395 | |||
| 396 | if((fd = open(efname, O_RDONLY)) < 0) | ||
| 397 | error(1, errno, "Could not open encrypted file for decrypting"); | ||
| 398 | if((tfd = maketmp(xdirname(dfname))) < 0) | ||
| 399 | error(1, errno, "Could not open temp file for holding decrypted data"); | ||
| 400 | |||
| 401 | // Read header in from the file | ||
| 402 | memset(header, 0, sizeof(header)); | ||
| 403 | if(read(fd, header, sizeof(header)) < 0) | ||
| 404 | error(1, errno, "read() error while getting the header"); | ||
| 405 | |||
| 406 | // Make sure the header is correct | ||
| 407 | crypto_secretstream_xchacha20poly1305_state nstate; | ||
| 408 | if(crypto_secretstream_xchacha20poly1305_init_pull(&nstate, header, key) != 0) | ||
| 409 | error(1, errno, "ran into a corrupted header"); | ||
| 410 | |||
| 411 | bytesread = -1; unsigned long long mlen = 0; unsigned char tag = 0; | ||
| 412 | buf = xcalloc(CHUNK_SIZE + 1, sizeof(*buf)); | ||
| 413 | cbuf = xcalloc((CHUNK_SIZE + 1) + crypto_secretstream_xchacha20poly1305_ABYTES, sizeof(*cbuf)); | ||
| 414 | while((bytesread = read(fd, cbuf, (CHUNK_SIZE + 1) + crypto_secretstream_xchacha20poly1305_ABYTES)) >= 0) { | ||
| 415 | if(crypto_secretstream_xchacha20poly1305_pull(&nstate, buf, &mlen, &tag, cbuf, bytesread, NULL, 0) != 0) { | ||
| 416 | error(1, errno, "Ran into a corrupted chunk while decrypting"); | ||
| 417 | } | ||
| 418 | |||
| 419 | // Do some error checking | ||
| 420 | if(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && bytesread != 0) | ||
| 421 | error(1, errno, "Found an end tag before the end of the file"); | ||
| 422 | if(bytesread == 0 && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) | ||
| 423 | error(1, errno, "Hit the end of the file before the end tag"); | ||
| 424 | if(writewholebuffer(tfd, buf, mlen) < 0) | ||
| 425 | error(1, errno, "Ran into a write() error while writing decrypted file contents to the tmp file"); | ||
| 426 | |||
| 427 | |||
| 428 | if(bytesread == 0) | ||
| 429 | break; | ||
| 430 | } | ||
| 431 | if(bytesread < 0) | ||
| 432 | error(1, errno, "read() error while decrypting"); | ||
| 433 | |||
| 434 | // Link the temp file back into the system | ||
| 435 | asprintf(&path, "/proc/self/fd/%d", tfd); | ||
| 436 | if(!path) | ||
| 437 | abort(); | ||
| 438 | remove(dfname); // Make sure an old version isn't sticking around | ||
| 439 | linkat(AT_FDCWD, path, AT_FDCWD, dfname, AT_SYMLINK_FOLLOW); | ||
| 440 | |||
| 441 | //*/// | ||
| 442 | |||
| 443 | |||
| 444 | /*// Sample code to encrypt a file using encrypttotmp | ||
| 445 | |||
| 446 | unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]; | ||
| 447 | crypto_secretstream_xchacha20poly1305_keygen(key); | ||
| 448 | |||
| 449 | encrypttotmp("main.c", "main.enc", key); | ||
| 450 | |||
| 451 | //*/// | ||
| 452 | |||
| 306 | return 0; | 453 | return 0; |
| 307 | } | 454 | } |
| 308 | 455 | ||
diff --git a/src/encryption.h b/src/encryption.h index c780e2b..1c38141 100644 --- a/src/encryption.h +++ b/src/encryption.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | // manually run `sodium_init()` in some main or init function of your own so that you can deal with a potential error yourself | 6 | // manually run `sodium_init()` in some main or init function of your own so that you can deal with a potential error yourself |
| 7 | #define ___VXGG___ALWAYS_CHECK_LIBSODIUM___ 0 | 7 | #define ___VXGG___ALWAYS_CHECK_LIBSODIUM___ 0 |
| 8 | 8 | ||
| 9 | #define CHUNK_SIZE ((int)(1 << 12)) | ||
| 10 | |||
| 9 | #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 11 | #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| 10 | 12 | ||
| 11 | // Definition for the callback function that fires when a call to checksodium fails | 13 | // Definition for the callback function that fires when a call to checksodium fails |
diff --git a/src/shared.h b/src/shared.h index 9cdbd33..3c23676 100644 --- a/src/shared.h +++ b/src/shared.h | |||
| @@ -24,6 +24,12 @@ void* xreallocarray(void *ptr, size_t nmemb, size_t size); | |||
| 24 | // Read the entire contents of a file descriptor into a malloc()'ed buffer | 24 | // Read the entire contents of a file descriptor into a malloc()'ed buffer |
| 25 | int readwholebuffer(char **str, unsigned long int initsize, int fd); | 25 | int readwholebuffer(char **str, unsigned long int initsize, int fd); |
| 26 | 26 | ||
| 27 | // Write the entire contents of a buffer into a file descriptor | ||
| 27 | int writewholebuffer(int fd, const unsigned char *buf, int len); | 28 | int writewholebuffer(int fd, const unsigned char *buf, int len); |
| 28 | 29 | ||
| 30 | // `dirname()` reimplementation that returns a malloc()'ed string. According to the `x___` naming scheme, exits on alloc error. | ||
| 31 | // `___VXGG___XALLOC_EXIT_ON_ERROR___` influences whether `exit()` or `abort()` is called on error, and `___VXGG___VERBOSE_ERRORS___` | ||
| 32 | // influences whether diagnostic error messages are printed | ||
| 33 | char *xdirname(const char * const path); | ||
| 34 | |||
| 29 | #endif \ No newline at end of file | 35 | #endif \ No newline at end of file |
