Skip to content

Instantly share code, notes, and snippets.

@leto
Created February 23, 2020 14:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leto/1a984b1daa710ed55464c093640d6769 to your computer and use it in GitHub Desktop.
Save leto/1a984b1daa710ed55464c093640d6769 to your computer and use it in GitHub Desktop.
libsodium file encryption example
#include <stdio.h>
#include <sodium.h>
#define CHUNK_SIZE 4096
static int
encrypt(const char *target_file, const char *source_file,
const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES])
{
unsigned char buf_in[CHUNK_SIZE];
unsigned char buf_out[CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES];
unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
crypto_secretstream_xchacha20poly1305_state st;
FILE *fp_t, *fp_s;
unsigned long long out_len;
size_t rlen;
int eof;
unsigned char tag;
fp_s = fopen(source_file, "rb");
fp_t = fopen(target_file, "wb");
crypto_secretstream_xchacha20poly1305_init_push(&st, header, key);
fwrite(header, 1, sizeof header, fp_t);
do {
rlen = fread(buf_in, 1, sizeof buf_in, fp_s);
eof = feof(fp_s);
tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
crypto_secretstream_xchacha20poly1305_push(&st, buf_out, &out_len, buf_in, rlen,
NULL, 0, tag);
fwrite(buf_out, 1, (size_t) out_len, fp_t);
} while (! eof);
fclose(fp_t);
fclose(fp_s);
return 0;
}
static int
decrypt(const char *target_file, const char *source_file,
const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES])
{
unsigned char buf_in[CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES];
unsigned char buf_out[CHUNK_SIZE];
unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
crypto_secretstream_xchacha20poly1305_state st;
FILE *fp_t, *fp_s;
unsigned long long out_len;
size_t rlen;
int eof;
int ret = -1;
unsigned char tag;
fp_s = fopen(source_file, "rb");
fp_t = fopen(target_file, "wb");
fread(header, 1, sizeof header, fp_s);
if (crypto_secretstream_xchacha20poly1305_init_pull(&st, header, key) != 0) {
goto ret; /* incomplete header */
}
do {
rlen = fread(buf_in, 1, sizeof buf_in, fp_s);
eof = feof(fp_s);
if (crypto_secretstream_xchacha20poly1305_pull(&st, buf_out, &out_len, &tag,
buf_in, rlen, NULL, 0) != 0) {
goto ret; /* corrupted chunk */
}
if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && ! eof) {
goto ret; /* premature end (end of file reached before the end of the stream) */
}
fwrite(buf_out, 1, (size_t) out_len, fp_t);
} while (! eof);
ret = 0;
ret:
fclose(fp_t);
fclose(fp_s);
return ret;
}
int
main(void)
{
unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES];
if (sodium_init() != 0) {
return 1;
}
crypto_secretstream_xchacha20poly1305_keygen(key);
if (encrypt("/tmp/encrypted", "/tmp/original", key) != 0) {
return 1;
}
if (decrypt("/tmp/decrypted", "/tmp/encrypted", key) != 0) {
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment