Last active
May 21, 2018 00:29
-
-
Save nolash/2d641c8c931134bfc8f275abd3e51d9d to your computer and use it in GitHub Desktop.
example on encryption using libsodium kdf key
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <sodium.h> | |
#include <string.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <sys/stat.h> | |
#define SUBKEYS_COUNT 8 | |
#define SUBKEYS_SIZE crypto_secretstream_xchacha20poly1305_KEYBYTES | |
#define SUBKEYS_CONTEXT "foo" | |
#define CHUNK_SIZE 2048 | |
// creates a key and derives subkeys | |
// if salt file exists it will use it, and result will be the same as the round which saved the salt | |
// encrypts a file "argon2.dat" (must add manual) with the last subkey, decrypts it with same key and outputs first few bytes of plaintext | |
int main() { | |
int r, i, j; | |
int fd_in, fd_out; | |
unsigned char key[crypto_box_SEEDBYTES]; | |
unsigned char salt[crypto_pwhash_SALTBYTES]; | |
const char *pass = "foo bar baz xyzzy"; | |
struct stat st; | |
unsigned char subkeys[SUBKEYS_COUNT][SUBKEYS_SIZE]; | |
unsigned char enc_buf_plain[CHUNK_SIZE]; | |
unsigned char enc_buf_cipher[CHUNK_SIZE+crypto_secretstream_xchacha20poly1305_ABYTES]; | |
unsigned char enc_header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | |
crypto_secretstream_xchacha20poly1305_state enc_st; | |
unsigned long long outlen; | |
unsigned char tag; | |
// if we have salt, use it | |
fd_in = open("salt.bin", O_RDONLY, NULL); | |
if (fd_in < 0) { | |
randombytes_buf(salt, sizeof(salt)); | |
} else { | |
r = read(fd_in, salt, sizeof(salt));// better if check length of file | |
if (r < sizeof(salt)) { | |
close(fd_in); | |
return 1; | |
} | |
} | |
close(fd_in); | |
// create key | |
r = crypto_pwhash(key, sizeof(key), pass, strlen(pass), salt, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE, crypto_pwhash_ALG_DEFAULT); | |
if (r) { | |
return 1; | |
} | |
// save key (of course we never do this in real life) | |
fd_out = open("key.bin", O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU); | |
if (fd_out < 0) { | |
return 2; | |
} | |
r = write(fd_out, key, sizeof(key)); | |
if (r != sizeof(key)) { | |
return 2; | |
} | |
close(fd_out); | |
// save salt | |
fd_out = open("salt.bin", O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU); | |
if (fd_out < 0) { | |
return 3; | |
} | |
r = write(fd_out, salt, sizeof(salt)); | |
if (r != sizeof(salt)) { | |
return 3; | |
} | |
close(fd_out); | |
// create subkeys and show them | |
for (i = 0; i < SUBKEYS_COUNT; i++) { | |
crypto_kdf_derive_from_key(subkeys[i], SUBKEYS_SIZE, i, SUBKEYS_CONTEXT, key); | |
} | |
for (i = 0; i < SUBKEYS_COUNT; i++) { | |
printf("key #%d: ", i); | |
for (j = 0; j < SUBKEYS_SIZE; j++) { | |
printf("%02x", subkeys[i][j]); | |
} | |
printf("\n"); | |
} | |
// choose the last subkey to encrypt | |
fd_in = open("argon2.dat", O_RDONLY, NULL); | |
if (fd_in < 0) { | |
return 4; | |
} | |
fd_out = open("argon2.enc", O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU); | |
if (fd_out < 0) { | |
close(fd_in); | |
return 4; | |
} | |
crypto_secretstream_xchacha20poly1305_init_push(&enc_st, enc_header, subkeys[SUBKEYS_COUNT-1]); | |
r = write(fd_out, enc_header, sizeof(enc_header)); | |
if (r < sizeof(enc_header)) { | |
close(fd_out); | |
close(fd_in); | |
return 5; | |
} | |
do { | |
r = read(fd_in, enc_buf_plain, sizeof(enc_buf_plain)); | |
tag = r ? 0 : crypto_secretstream_xchacha20poly1305_TAG_FINAL; | |
crypto_secretstream_xchacha20poly1305_push(&enc_st, enc_buf_cipher, &outlen, enc_buf_plain, r, NULL, 0, tag); | |
write(fd_out, enc_buf_cipher, outlen); | |
} while (r); | |
close(fd_out); | |
close(fd_in); | |
// decrypt | |
fd_in = (open("argon2.enc", O_RDONLY, NULL)); | |
r = read(fd_in, enc_header, sizeof(enc_header)); | |
if (crypto_secretstream_xchacha20poly1305_init_pull(&enc_st, enc_header, subkeys[SUBKEYS_COUNT-1])) { | |
close(fd_in); | |
return 6; | |
} | |
r = read(fd_in, enc_buf_cipher, sizeof(enc_buf_cipher)); | |
if (r<=0) { | |
close(fd_in); | |
return 7; | |
} | |
r = crypto_secretstream_xchacha20poly1305_pull(&enc_st, enc_buf_plain, &outlen, &tag, enc_buf_cipher, r, NULL, 0); | |
if (r) { | |
close(fd_in); | |
return 8; | |
} | |
close(fd_in); | |
// show a few bytes | |
*(enc_buf_plain+256)=0; | |
printf("%s\n", enc_buf_plain); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment