diff --git a/demos/.gitignore b/demos/.gitignore new file mode 100644 index 00000000..9b7faddc --- /dev/null +++ b/demos/.gitignore @@ -0,0 +1,11 @@ +auth +box +generhash +generhashstream +hash +Makefile +onetimeauth +sretbox +shorthash +sign +stream diff --git a/demos/auth.c b/demos/auth.c new file mode 100644 index 00000000..d801f08b --- /dev/null +++ b/demos/auth.c @@ -0,0 +1,68 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * Full featured authentication which is used to verify that the message + * comes from the expected person. It should be safe to keep the same key + * for multiple messages. + */ +static int +auth(void) +{ + unsigned char k[crypto_auth_KEYBYTES]; /* key */ + unsigned char a[crypto_auth_BYTES]; /* authentication token */ + unsigned char m[BUFFER_SIZE]; /* message */ + size_t mlen; /* message length */ + int r; + + sodium_memzero(k, sizeof k); /* must zero the key */ + + puts("Example: crypto_auth\n"); + + prompt_input("Input your key > ", (char*) k, sizeof k); + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); + putchar('\n'); + + printf("Generating %s authentication...\n", crypto_auth_primitive()); + crypto_auth(a, m, mlen, k); + + puts("Format: authentication token::message"); + print_hex(a, sizeof a); + fputs("::", stdout); + puts((const char*) m); + putchar('\n'); + + puts("Verifying authentication..."); + r = crypto_auth_verify(a, m, mlen, k); + print_verification(r); + + sodium_memzero(k, sizeof k); /* wipe sensitive data */ + sodium_memzero(a, sizeof a); + sodium_memzero(m, sizeof m); + return r; +} + +int +main(int argc, char **argv) +{ + int r; + + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + r = (0 == auth() ? EXIT_SUCCESS : EXIT_FAILURE); + exit(r); +} + diff --git a/demos/box.c b/demos/box.c new file mode 100644 index 00000000..5ebd2014 --- /dev/null +++ b/demos/box.c @@ -0,0 +1,157 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * Shows how crypto_box works using Bob and Alice with a simple message. + * Both clients must generate their own key pair and swap public key. The + * library will perform Diffie-Hellman to generate a shared key for + * symmetric encryption. + * + * Note that crypto_box uses padding at the start of both messages. + * The padding must be zero else the encryption or decryption will fail. + * + * Encrypted messages will be 16 bytes longer because a 16 byte + * authentication token will be prepended to the message. + * + * Note the same nonce must not be used; it should be safe to use a counter. + */ +static int +box(void) +{ + unsigned char bob_pk[crypto_box_PUBLICKEYBYTES]; /* Bob public */ + unsigned char bob_sk[crypto_box_SECRETKEYBYTES]; /* Bob secret */ + unsigned char bob_ss[crypto_box_BEFORENMBYTES]; /* Bob session */ + + unsigned char alice_pk[crypto_box_PUBLICKEYBYTES]; /* Alice public */ + unsigned char alice_sk[crypto_box_SECRETKEYBYTES]; /* Alice secret */ + unsigned char alice_ss[crypto_box_BEFORENMBYTES]; /* Alice session */ + + unsigned char n[crypto_box_NONCEBYTES]; /* message nonce */ + unsigned char m[BUFFER_SIZE + crypto_box_ZEROBYTES];/* plaintext */ + unsigned char c[BUFFER_SIZE + crypto_box_ZEROBYTES];/* ciphertext */ + size_t mlen; /* length */ + int r; + + puts("Example: crypto_box\n"); + + puts("Generating keypairs...\n"); + crypto_box_keypair(bob_pk, bob_sk); /* generate Bob's keys */ + crypto_box_keypair(alice_pk, alice_sk); /* generate Alice's keys */ + + puts("Bob"); + fputs("Public: ", stdout); + print_hex(bob_pk, sizeof bob_pk); + putchar('\n'); + fputs("Secret: ", stdout); + print_hex(bob_sk, sizeof bob_sk); + putchar('\n'); + putchar('\n'); + + puts("Alice"); + fputs("Public: ", stdout); + print_hex(alice_pk, sizeof alice_pk); + putchar('\n'); + fputs("Secret: ", stdout); + print_hex(alice_sk, sizeof alice_sk); + putchar('\n'); + putchar('\n'); + + /* perform diffie hellman */ + crypto_box_beforenm(bob_ss, alice_pk, bob_sk); + crypto_box_beforenm(alice_ss, bob_pk, alice_sk); + fputs("Bob shared key: ", stdout); + print_hex(bob_ss, sizeof bob_ss); + putchar('\n'); + fputs("Alice shared key: ", stdout); + print_hex(alice_ss, sizeof alice_ss); + putchar('\n'); + putchar('\n'); + + /* nonce must be generated per message, safe to send with message */ + puts("Generating nonce..."); + randombytes_buf(n, sizeof n); + fputs("Nonce: ", stdout); + print_hex(n, sizeof n); + putchar('\n'); + putchar('\n'); + + /* read input */ + mlen = prompt_input("Input your message > ", + (char*) m + crypto_box_ZEROBYTES, + sizeof m - crypto_box_ZEROBYTES); + + /* must zero at least the padding */ + sodium_memzero(m, crypto_box_ZEROBYTES); + + puts("Notice the 32 bytes of zero"); + print_hex(m, mlen + crypto_box_ZEROBYTES); + putchar('\n'); + putchar('\n'); + + /* encrypt the message */ + printf("Encrypting with %s\n\n", crypto_box_primitive()); + crypto_box_afternm(c, m, mlen + crypto_box_ZEROBYTES, n, bob_ss); + + /* sent message */ + puts("Bob sending message...\n"); + puts("Notice the prepended 16 byte authentication token"); + puts("Format: nonce::message"); + fputs("Ciphertext: ", stdout); + print_hex(n, sizeof n); + fputs("::", stdout); + print_hex(c, mlen + crypto_box_ZEROBYTES); + putchar('\n'); + putchar('\n'); + + /* decrypt the message */ + puts("Alice opening message..."); + + /* must zero at least the padding */ + sodium_memzero(c, crypto_box_BOXZEROBYTES); + r = crypto_box_open_afternm( + m, c, mlen + crypto_box_ZEROBYTES, + n, alice_ss); + + puts("Notice the 32 bytes of zero"); + print_hex(m, mlen + crypto_box_ZEROBYTES); + putchar('\n'); + + print_verification(r); + if (r == 0) printf("Plaintext: %s\n\n", m + crypto_box_ZEROBYTES); + + sodium_memzero(bob_pk, sizeof bob_pk); /* wipe sensitive data */ + sodium_memzero(bob_sk, sizeof bob_sk); + sodium_memzero(bob_ss, sizeof bob_ss); + sodium_memzero(alice_pk, sizeof alice_pk); + sodium_memzero(alice_sk, sizeof alice_sk); + sodium_memzero(alice_ss, sizeof alice_ss); + sodium_memzero(n, sizeof n); + sodium_memzero(m, sizeof m); + sodium_memzero(c, sizeof c); + return r; +} + +int +main(int argc, char **argv) +{ + int r; + + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + r = (0 == box() ? EXIT_SUCCESS : EXIT_FAILURE); + exit(r); +} + diff --git a/demos/demo_utils.c b/demos/demo_utils.c new file mode 100644 index 00000000..1387b10d --- /dev/null +++ b/demos/demo_utils.c @@ -0,0 +1,66 @@ +/* + * These are the utility functions shared by all demo programs. + */ +#include +#include +#include + +#include "sodium.h" /* library header */ + +#include "demo_utils.h" /* demo utility header */ + + + +/* ================================================================== * + * utility functions * + * ================================================================== */ + +/* + * Print hex. + */ +void +print_hex(const void *buf, const size_t len) +{ + const unsigned char *b; + char *p; + + b = buf; + p = malloc((len * 2 + 1) * (sizeof *b)); + + /* the library supplies a few utility functions like the one below */ + sodium_bin2hex(p, len * 2 + 1, b, len); + fputs(p, stdout); + free(p); +} + +/* + * Display a prompt for input by user. It will save the input into a buffer + * of a specific size with room for the null terminator while removing + * trailing newline characters. + */ +size_t +prompt_input(char *prompt, char *buf, const size_t len) +{ + size_t n; + + fputs(prompt, stdout); + fgets(buf, len, stdin); /* grab input with room for NULL */ + + n = strlen(buf); + if (buf[n - 1] == '\n') { /* trim excess new line */ + buf[n - 1] = '\0'; + --n; + } + return n; +} + +/* + * Print a message if the function was sucessful or failed. + */ +void +print_verification(int r) +{ + if (r == 0) puts("Success\n"); + else puts("Failure\n"); +} + diff --git a/demos/demo_utils.h b/demos/demo_utils.h new file mode 100644 index 00000000..ae35d8d7 --- /dev/null +++ b/demos/demo_utils.h @@ -0,0 +1,22 @@ +/* + * Utility functions shared by all the demo programs. + */ +#ifndef DEMO_UTILS_H +#define DEMO_UTILS_H + + +#include + + +#define BUFFER_SIZE 128 /* size of all input buffers in the demo */ + + + +void print_hex(const void *buf, const size_t len); +size_t prompt_input(char *prompt, char *buf, const size_t len); +void print_verification(int r); + + + +#endif /* DEMO_UTILS_H */ + diff --git a/demos/generichash.c b/demos/generichash.c new file mode 100644 index 00000000..a8b2d435 --- /dev/null +++ b/demos/generichash.c @@ -0,0 +1,57 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * Generic hash is intended as a variable output hash with enough strength + * to ensure data integrity. The hash out put is also able to vary in size. + * Key is optional and is able to vary in size. + * + * Note that it is recommended to stay within the range of MIN and MAX + * output because larger output will produce gaps. + */ +void +generichash(void) +{ + unsigned char k[crypto_generichash_KEYBYTES_MAX]; /* key */ + unsigned char h[crypto_generichash_BYTES_MIN]; /* hash output */ + unsigned char m[BUFFER_SIZE]; /* message */ + size_t mlen; /* length */ + + puts("Example: crypto_generichash\n"); + + sodium_memzero(k, sizeof k); + prompt_input("Input your key > ", (char*) k, sizeof k); + + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); + putchar('\n'); + + printf("Hashing message with %s\n", crypto_generichash_primitive()); + crypto_generichash(h, sizeof h, m, mlen, k, sizeof k); + fputs("Hash: ", stdout); + print_hex(h, sizeof h); + putchar('\n'); + putchar('\n'); +} + +int +main(int argc, char **argv) +{ + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + generichash(); + exit(EXIT_SUCCESS); +} + diff --git a/demos/generichashstream.c b/demos/generichashstream.c new file mode 100644 index 00000000..63d7a2e6 --- /dev/null +++ b/demos/generichashstream.c @@ -0,0 +1,66 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * Streaming variant of generic hash. This has the ability to hash + * data in chunks at a time and compute the same result as hashing + * all of the data at once. + */ +void +generichashstream(void) +{ + unsigned char k[crypto_generichash_KEYBYTES_MAX]; /* key */ + unsigned char h[crypto_generichash_BYTES_MIN]; /* hash output */ + crypto_generichash_state state; /* hash stream */ + unsigned char m[BUFFER_SIZE]; /* input buffer */ + size_t mlen; /* input length */ + + puts("Example: crypto_generichashstream\n"); + + sodium_memzero(k, sizeof k); + prompt_input("Input your key > ", (char*) k, sizeof k); + putchar('\n'); + + printf("Hashing message with %s\n", crypto_generichash_primitive()); + + /* initialize the stream */ + crypto_generichash_init(&state, k, sizeof k, sizeof h); + + while (1) { + mlen = prompt_input("> ", (char*) m, sizeof m); + if (mlen == 0) break; + + /* keep appending data */ + crypto_generichash_update(&state, m, mlen); + } + crypto_generichash_final(&state, h, sizeof h); + putchar('\n'); + + fputs("Hash: ", stdout); + print_hex(h, sizeof h); + putchar('\n'); + putchar('\n'); +} + +int +main(int argc, char **argv) +{ + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + generichashstream(); + exit(EXIT_SUCCESS); +} + diff --git a/demos/hash.c b/demos/hash.c new file mode 100644 index 00000000..167a3b26 --- /dev/null +++ b/demos/hash.c @@ -0,0 +1,49 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * The library ships with a one-shot SHA-512 implementation. Simply allocate + * all desired data into a single continuous buffer. + */ +static void +hash(void) +{ + unsigned char h[crypto_hash_BYTES]; /* hash output */ + unsigned char m[BUFFER_SIZE]; /* message */ + size_t mlen; /* length */ + + puts("Example: crypto_hash\n"); + + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); + putchar('\n'); + + printf("Hashing message with %s\n", crypto_hash_primitive()); + crypto_hash(h, m, mlen); + fputs("Hash: ", stdout); + print_hex(h, sizeof h); + putchar('\n'); + putchar('\n'); +} + +int +main(int argc, char **argv) +{ + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + hash(); + exit(EXIT_SUCCESS); +} + diff --git a/demos/onetimeauth.c b/demos/onetimeauth.c new file mode 100644 index 00000000..c9b47189 --- /dev/null +++ b/demos/onetimeauth.c @@ -0,0 +1,71 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * This method is only effective for a single use per key. The benefit is + * the algorithm is quicker and output is half the size of auth. It is easy + * to see how weak the algorithm is when you use a one letter key. + * + * Note that the same key must not be used more than once. + */ +static int +onetimeauth(void) +{ + unsigned char k[crypto_onetimeauth_KEYBYTES];/* key */ + unsigned char a[crypto_onetimeauth_BYTES]; /* authentication */ + unsigned char m[BUFFER_SIZE]; /* message */ + size_t mlen; /* message length */ + int r; + + sodium_memzero(k, sizeof k); /* must zero the key */ + + puts("Example: crypto_onetimeauth\n"); + + prompt_input("Input your key > ", (char*) k, sizeof k); + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); + putchar('\n'); + + printf("Generating %s authentication...\n", + crypto_onetimeauth_primitive()); + crypto_onetimeauth(a, m, mlen, k); + + puts("Format: authentication token::message"); + print_hex(a, sizeof a); + fputs("::", stdout); + puts((const char*) m); + putchar('\n'); + + puts("Verifying authentication..."); + r = crypto_onetimeauth_verify(a, m, mlen, k); + print_verification(r); + + sodium_memzero(k, sizeof k); /* wipe sensitive data */ + sodium_memzero(a, sizeof a); + sodium_memzero(m, sizeof m); + return r; +} + +int +main(int argc, char **argv) +{ + int r; + + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + r = (0 == onetimeauth() ? EXIT_SUCCESS : EXIT_FAILURE); + exit(r); +} + diff --git a/demos/secretbox.c b/demos/secretbox.c new file mode 100644 index 00000000..4a043f24 --- /dev/null +++ b/demos/secretbox.c @@ -0,0 +1,110 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * This is a wrapper around stream which does XOR automatically. + * + * Note that the buffer must be padded at the front. The same nonce must + * not be used; it should be safe to use a counter. + * + * Encrypted messages will be 16 bytes longer because a 16 byte + * authentication token will be prepended to the message. + */ +static int +secretbox(void) +{ + unsigned char k[crypto_secretbox_KEYBYTES]; /* secret */ + unsigned char n[crypto_secretbox_NONCEBYTES]; /* nonce */ + unsigned char m[BUFFER_SIZE + crypto_secretbox_ZEROBYTES]; /* plain */ + unsigned char c[BUFFER_SIZE + crypto_secretbox_ZEROBYTES]; /* cipher */ + size_t mlen; /* length */ + int r; + + puts("Example: crypto_secretbox\n"); + + sodium_memzero(k, sizeof k); + prompt_input("Input your key > ", (char*) k, sizeof k); + + /* nonce must be generated per message, safe to send with message */ + puts("Generating nonce..."); + randombytes_buf(n, sizeof n); + fputs("Nonce: ", stdout); + print_hex(n, sizeof n); + putchar('\n'); + putchar('\n'); + + mlen = prompt_input("Input your message > ", + (char*) m + crypto_secretbox_ZEROBYTES, + sizeof m - crypto_secretbox_ZEROBYTES); + + /* must zero at least the padding */ + sodium_memzero(m, crypto_secretbox_ZEROBYTES); + + puts("Notice the 32 bytes of zero"); + print_hex(m, mlen + crypto_box_ZEROBYTES); + putchar('\n'); + + /* encrypting message */ + printf("Encrypting with %s\n", crypto_secretbox_primitive()); + + crypto_secretbox(c, m, mlen + crypto_secretbox_ZEROBYTES, n, k); + putchar('\n'); + + puts("Notice the prepended 16 byte authentication token"); + puts("Sending message..."); + puts("Format: nonce::message"); + fputs("Ciphertext: ", stdout); + print_hex(n, sizeof n); + fputs("::", stdout); + print_hex(c, mlen + crypto_secretbox_ZEROBYTES); + putchar('\n'); + putchar('\n'); + + /* decrypting message */ + puts("Opening message..."); + + /* must zero at least the padding */ + sodium_memzero(c, crypto_secretbox_BOXZEROBYTES); + r = crypto_secretbox_open( + m, c, mlen + crypto_secretbox_ZEROBYTES, n, k); + + puts("Notice the 32 bytes of zero"); + print_hex(m, mlen + crypto_box_ZEROBYTES); + putchar('\n'); + putchar('\n'); + + print_verification(r); + if (r == 0) printf("Plaintext: %s\n\n", + m + crypto_secretbox_ZEROBYTES); + + sodium_memzero(k, sizeof k); /* wipe sensitive data */ + sodium_memzero(n, sizeof n); + sodium_memzero(m, sizeof m); + sodium_memzero(c, sizeof c); + return r; +} + +int +main(int argc, char **argv) +{ + int r; + + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + r = (0 == secretbox() ? EXIT_SUCCESS : EXIT_FAILURE); + exit(r); +} + diff --git a/demos/shorthash.c b/demos/shorthash.c new file mode 100644 index 00000000..fb12ce1f --- /dev/null +++ b/demos/shorthash.c @@ -0,0 +1,54 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * Short hash is a fast algorithm intended for hash tables and anything + * else that does not require data integrity. There is the added benefit + * of a key which will alter the output of the hash. + */ +void +shorthash(void) +{ + unsigned char k[crypto_shorthash_KEYBYTES]; /* key */ + unsigned char h[crypto_shorthash_BYTES]; /* hash output */ + unsigned char m[BUFFER_SIZE]; /* message */ + size_t mlen; /* length */ + + puts("Example: crypto_shorthash\n"); + + sodium_memzero(k, sizeof k); + prompt_input("Input your key > ", (char*) k, sizeof k); + + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); + putchar('\n'); + + printf("Hashing message with %s\n", crypto_shorthash_primitive()); + crypto_shorthash(h, m, mlen, k); + fputs("Hash: ", stdout); + print_hex(h, sizeof h); + putchar('\n'); + putchar('\n'); +} + +int +main(int argc, char **argv) +{ + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + shorthash(); + exit(EXIT_SUCCESS); +} + diff --git a/demos/sign.c b/demos/sign.c new file mode 100644 index 00000000..08120982 --- /dev/null +++ b/demos/sign.c @@ -0,0 +1,86 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * Signs a message with secret key which will authenticate a message. + * Everybody else can use the public key to ensure that the message is both + * valid and untampered. + * + * Note that both message and signed message must be padded for signature. + * The padding does not have to be set to zero. + */ +static int +sign(void) +{ + unsigned char pk[crypto_sign_PUBLICKEYBYTES]; /* Bob public */ + unsigned char sk[crypto_sign_SECRETKEYBYTES]; /* Bob secret */ + unsigned char m[BUFFER_SIZE + crypto_sign_BYTES]; /* message */ + unsigned char sm[BUFFER_SIZE + crypto_sign_BYTES]; /* signed message */ + unsigned long long int mlen; /* message length */ + unsigned long long int smlen; /* signed length */ + int r; + + puts("Example: crypto_sign\n"); + + puts("Generating keypair..."); + crypto_sign_keypair(pk, sk); /* generate Bob's keys */ + + fputs("Public: ", stdout); + print_hex(pk, sizeof pk); + putc('\n', stdout); + fputs("Secret: ", stdout); + print_hex(sk, sizeof sk); + puts("\n"); + + /* read input */ + mlen = prompt_input("Input your message > ", + (char*) m, sizeof m - crypto_sign_BYTES); + putc('\n', stdout); + + printf("Signing message with %s...\n", crypto_sign_primitive()); + crypto_sign(sm, &smlen, m, mlen, sk); + + puts("Format: signature::message"); + fputs("Signed: ", stdout); + print_hex(sm, crypto_sign_BYTES); + fputs("::", stdout); + puts((const char*) sm + crypto_sign_BYTES); + putc('\n', stdout); + + puts("Validating message..."); + r = crypto_sign_open(m, &mlen, sm, smlen, pk); + + print_verification(r); + if (r == 0) printf("Message: %s\n\n", m); + + sodium_memzero(pk, sizeof pk); /* wipe sensitive data */ + sodium_memzero(sk, sizeof sk); + sodium_memzero(m, sizeof m); + sodium_memzero(sm, sizeof sm); + return r; +} + +int +main(int argc, char **argv) +{ + int r; + + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + r = (0 == sign() ? EXIT_SUCCESS : EXIT_FAILURE); + exit(r); +} + diff --git a/demos/stream.c b/demos/stream.c new file mode 100644 index 00000000..459748e7 --- /dev/null +++ b/demos/stream.c @@ -0,0 +1,90 @@ +/* + * GraxRabble + * 05 May 2014 + * Demo programs for libsodium. + */ +#include +#include +#include + +#include /* library header */ + +#include "demo_utils.h" /* utility functions shared by demos */ + + + +/* + * Stream utilizes a nonce to generate a sequence of bytes. The library has + * an internal function which XOR data and the stream into an encrypted result. + * + * Note that this method does not supply authentication. Try secretbox instead. + * + * Note that nonce must be different for each message since it provides + * change between each operation. It should be safe to use a counter + * instead of purely random data each time. + */ +static int +stream(void) +{ + unsigned char k[crypto_stream_KEYBYTES]; /* secret key */ + unsigned char n[crypto_stream_NONCEBYTES]; /* message nonce */ + unsigned char m[BUFFER_SIZE]; /* plain-text */ + unsigned char c[BUFFER_SIZE]; /* cipher-text */ + size_t mlen; /* length */ + int r; + + puts("Example: crypto_stream\n"); + + sodium_memzero(k, sizeof k); + prompt_input("Input your key > ", (char*) k, sizeof k); + putchar('\n'); + + /* nonce must be generated per message, safe to send with message */ + puts("Generating nonce..."); + randombytes_buf(n, sizeof n); + fputs("Nonce: ", stdout); + print_hex(n, sizeof n); + putchar('\n'); + putchar('\n'); + + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); + putchar('\n'); + + printf("Encrypting with (xor) %s\n", crypto_stream_primitive()); + crypto_stream_xor(c, m, mlen, n, k); + putchar('\n'); + + puts("Sending message..."); + puts("Format: nonce::message"); + fputs("Ciphertext: ", stdout); + print_hex(n, sizeof n); + fputs("::", stdout); + print_hex(c, mlen); + putchar('\n'); + putchar('\n'); + + puts("Opening message..."); + r = crypto_stream_xor(m, c, mlen, n, k); + + print_verification(r); + if (r == 0) printf("Plaintext: %s\n\n", m); + + sodium_memzero(k, sizeof k); /* wipe sensitive data */ + sodium_memzero(n, sizeof n); + sodium_memzero(m, sizeof m); + sodium_memzero(c, sizeof c); + return r; +} + +int +main(int argc, char **argv) +{ + int r; + + sodium_init(); + printf("Using LibSodium %s\n", sodium_version_string()); + + r = (0 == stream() ? EXIT_SUCCESS : EXIT_FAILURE); + exit(r); +} +