From c78c9785929751e0722d94ded760889927ef429d Mon Sep 17 00:00:00 2001 From: GraxRabble Date: Wed, 24 Sep 2014 17:40:21 -0400 Subject: [PATCH 1/6] added gist examples into demos folder; you can figure out where this belongs --- demos/.gitignore | 11 +++ demos/auth.c | 68 +++++++++++++++++ demos/box.c | 157 ++++++++++++++++++++++++++++++++++++++ demos/demo_utils.c | 66 ++++++++++++++++ demos/demo_utils.h | 22 ++++++ demos/generichash.c | 57 ++++++++++++++ demos/generichashstream.c | 66 ++++++++++++++++ demos/hash.c | 49 ++++++++++++ demos/onetimeauth.c | 71 +++++++++++++++++ demos/secretbox.c | 110 ++++++++++++++++++++++++++ demos/shorthash.c | 54 +++++++++++++ demos/sign.c | 86 +++++++++++++++++++++ demos/stream.c | 90 ++++++++++++++++++++++ 13 files changed, 907 insertions(+) create mode 100644 demos/.gitignore create mode 100644 demos/auth.c create mode 100644 demos/box.c create mode 100644 demos/demo_utils.c create mode 100644 demos/demo_utils.h create mode 100644 demos/generichash.c create mode 100644 demos/generichashstream.c create mode 100644 demos/hash.c create mode 100644 demos/onetimeauth.c create mode 100644 demos/secretbox.c create mode 100644 demos/shorthash.c create mode 100644 demos/sign.c create mode 100644 demos/stream.c 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); +} + From 7ae583d19a89d1fcfdbd8b3f357bef258784d028 Mon Sep 17 00:00:00 2001 From: GraxRabble Date: Wed, 24 Sep 2014 19:39:35 -0400 Subject: [PATCH 2/6] patched all notied issues #192 except for crypto_box_afternm --- demos/.gitignore | 6 +++--- demos/auth.c | 14 ++++++++++++-- demos/demo_utils.c | 5 +++-- demos/onetimeauth.c | 11 +++++++++++ demos/sign.c | 12 +++++++++++- 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/demos/.gitignore b/demos/.gitignore index 9b7faddc..a2cb8b4a 100644 --- a/demos/.gitignore +++ b/demos/.gitignore @@ -1,11 +1,11 @@ auth box -generhash -generhashstream +generichash +generichashstream hash Makefile onetimeauth -sretbox +secretbox shorthash sign stream diff --git a/demos/auth.c b/demos/auth.c index d801f08b..77dd3df4 100644 --- a/demos/auth.c +++ b/demos/auth.c @@ -27,11 +27,21 @@ auth(void) size_t mlen; /* message length */ int r; - sodium_memzero(k, sizeof k); /* must zero the key */ puts("Example: crypto_auth\n"); - + + /* + * Keys are entered as ascii values. The key is zeroed to + * maintain consistency. Input is read through a special + * function which reads exactly n bytes into a buffer to + * prevent buffer overflows. + */ + sodium_memzero(k, sizeof k); prompt_input("Input your key > ", (char*) k, sizeof k); + puts("Your key that you entered"); + print_hex(k, sizeof k); + putchar('\n'); + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); putchar('\n'); diff --git a/demos/demo_utils.c b/demos/demo_utils.c index 1387b10d..f0c4b917 100644 --- a/demos/demo_utils.c +++ b/demos/demo_utils.c @@ -16,7 +16,8 @@ * ================================================================== */ /* - * Print hex. + * Print hex is a wrapper around sodium_bin2hex which uses calloc + * to allocate temporary memory then immediately printing the result. */ void print_hex(const void *buf, const size_t len) @@ -25,7 +26,7 @@ print_hex(const void *buf, const size_t len) char *p; b = buf; - p = malloc((len * 2 + 1) * (sizeof *b)); + p = calloc(len * 2 + 1, sizeof *b); /* the library supplies a few utility functions like the one below */ sodium_bin2hex(p, len * 2 + 1, b, len); diff --git a/demos/onetimeauth.c b/demos/onetimeauth.c index c9b47189..fcacdbb8 100644 --- a/demos/onetimeauth.c +++ b/demos/onetimeauth.c @@ -33,7 +33,18 @@ onetimeauth(void) puts("Example: crypto_onetimeauth\n"); + /* + * Keys are entered as ascii values. The key is zeroed to + * maintain consistency. Input is read through a special + * function which reads exactly n bytes into a buffer to + * prevent buffer overflows. + */ + sodium_memzero(k, sizeof k); prompt_input("Input your key > ", (char*) k, sizeof k); + puts("Your key that you entered"); + print_hex(k, sizeof k); + putchar('\n'); + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); putchar('\n'); diff --git a/demos/sign.c b/demos/sign.c index 08120982..3ca8f06c 100644 --- a/demos/sign.c +++ b/demos/sign.c @@ -26,7 +26,7 @@ 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 m[BUFFER_SIZE]; /* 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 */ @@ -48,10 +48,20 @@ sign(void) mlen = prompt_input("Input your message > ", (char*) m, sizeof m - crypto_sign_BYTES); putc('\n', stdout); + + puts("Notice the message has no prepended padding"); + print_hex(m, mlen); + putchar('\n'); + putchar('\n'); printf("Signing message with %s...\n", crypto_sign_primitive()); crypto_sign(sm, &smlen, m, mlen, sk); + puts("Notice the signed message has prepended signature"); + print_hex(sm, smlen); + putchar('\n'); + putchar('\n'); + puts("Format: signature::message"); fputs("Signed: ", stdout); print_hex(sm, crypto_sign_BYTES); From 15ab5f6bf20efa0258b906d7bf770fd9829410cd Mon Sep 17 00:00:00 2001 From: GraxRabble Date: Wed, 24 Sep 2014 20:08:31 -0400 Subject: [PATCH 3/6] moved box.c to box_old.c and made a new box.c with --- demos/.gitignore | 1 + demos/box.c | 50 ++++----------- demos/box_old.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 37 deletions(-) create mode 100644 demos/box_old.c diff --git a/demos/.gitignore b/demos/.gitignore index a2cb8b4a..9e4e2cf2 100644 --- a/demos/.gitignore +++ b/demos/.gitignore @@ -1,5 +1,6 @@ auth box +box_old generichash generichashstream hash diff --git a/demos/box.c b/demos/box.c index 5ebd2014..022b8ab8 100644 --- a/demos/box.c +++ b/demos/box.c @@ -32,19 +32,17 @@ 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 */ + unsigned char m[BUFFER_SIZE]; /* plaintext */ + unsigned char c[BUFFER_SIZE + crypto_box_MACBYTES]; /* ciphertext */ size_t mlen; /* length */ int r; - puts("Example: crypto_box\n"); + puts("Example: crypto_box_easy\n"); puts("Generating keypairs...\n"); crypto_box_keypair(bob_pk, bob_sk); /* generate Bob's keys */ @@ -67,17 +65,6 @@ box(void) 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..."); @@ -88,21 +75,16 @@ box(void) putchar('\n'); /* read input */ - mlen = prompt_input("Input your message > ", - (char*) m + crypto_box_ZEROBYTES, - sizeof m - crypto_box_ZEROBYTES); + mlen = prompt_input("Input your message > ", (char*) m, sizeof m); - /* 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); + puts("Notice there is no padding"); + print_hex(m, mlen); 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); + crypto_box_easy(c, m, mlen, n, bob_pk, alice_sk); /* sent message */ puts("Bob sending message...\n"); @@ -111,32 +93,26 @@ box(void) fputs("Ciphertext: ", stdout); print_hex(n, sizeof n); fputs("::", stdout); - print_hex(c, mlen + crypto_box_ZEROBYTES); + print_hex(c, mlen + crypto_box_MACBYTES); 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); + r = crypto_box_open_easy(m, c, mlen + crypto_box_MACBYTES, + n, bob_pk, alice_sk); - puts("Notice the 32 bytes of zero"); - print_hex(m, mlen + crypto_box_ZEROBYTES); + puts("Notice there is no padding"); + print_hex(m, mlen); putchar('\n'); print_verification(r); - if (r == 0) printf("Plaintext: %s\n\n", m + crypto_box_ZEROBYTES); + if (r == 0) printf("Plaintext: %s\n\n", m); 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); diff --git a/demos/box_old.c b/demos/box_old.c new file mode 100644 index 00000000..7cc1f945 --- /dev/null +++ b/demos/box_old.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_afternm 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_afternm (archaic)\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); +} + From 2d8c08b01beb1ed23a48ed7d116be3de0d91fb04 Mon Sep 17 00:00:00 2001 From: GraxRabble Date: Wed, 24 Sep 2014 20:11:50 -0400 Subject: [PATCH 4/6] Got bob and alice mixed up on box.c:87 --- demos/box.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/box.c b/demos/box.c index 022b8ab8..a29d49bd 100644 --- a/demos/box.c +++ b/demos/box.c @@ -84,7 +84,7 @@ box(void) /* encrypt the message */ printf("Encrypting with %s\n\n", crypto_box_primitive()); - crypto_box_easy(c, m, mlen, n, bob_pk, alice_sk); + crypto_box_easy(c, m, mlen, n, alice_pk, bob_sk); /* sent message */ puts("Bob sending message...\n"); From e99748b1c07efe97a5ee77fab53836cd9d76d369 Mon Sep 17 00:00:00 2001 From: GraxRabble Date: Wed, 24 Sep 2014 20:13:01 -0400 Subject: [PATCH 5/6] removed comment about box_easy having to use padding --- demos/box.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/demos/box.c b/demos/box.c index a29d49bd..c2c93706 100644 --- a/demos/box.c +++ b/demos/box.c @@ -19,9 +19,6 @@ * 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. * From 44fed3dd0ed28cd8a4132e3162e2a600c37dc7f2 Mon Sep 17 00:00:00 2001 From: GraxRabble Date: Thu, 25 Sep 2014 13:21:44 -0400 Subject: [PATCH 6/6] fixed the comment about both message and signed message being padded --- demos/sign.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/demos/sign.c b/demos/sign.c index 3ca8f06c..345b436b 100644 --- a/demos/sign.c +++ b/demos/sign.c @@ -18,8 +18,9 @@ * 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. + * Note that the signed message will have 16 bytes of signature prepended. + * Ensure that the signed buffer is at least crypto_sign_BYTES longer then + * the actual message. */ static int sign(void)