#include #include #include #include #include bool key_contains_zero(unsigned char *key, unsigned int keylen) { bool has_zero = false; for (unsigned int i = 0; i < keylen; i++) { if (key[i] == 0) { has_zero = true; } } return has_zero; } void dump_key_as_c_code(FILE * f, const char *name, unsigned char *key, unsigned int keylen) { fprintf(f, "const unsigned char %s[] = { ", name); for (unsigned int i = 0; i < keylen; i++) { fprintf(f, "0x%02x", key[i]); if (i < keylen - 1) { fprintf(f, ", "); } } fprintf(f, " };\n"); fprintf(f, "const unsigned int %s_length = %d;\n", name, keylen); } void dump_key_as_exim_config(FILE * f, const char *name, unsigned char *key, unsigned int keylen) { // write a comment with C variable declaration fprintf(f, "# const unsigned char %s[%d] = { ", name, keylen); for (unsigned int i = 0; i < keylen; i++) { fprintf(f, "0x%02x", key[i]); if (i < keylen - 1) { fprintf(f, ", "); } } fprintf(f, " }; const unsigned int %s_length = %d;\n", name, keylen); // encode with base64 unsigned int b64len = sodium_base64_ENCODED_LEN(keylen, sodium_base64_VARIANT_ORIGINAL); unsigned char *b64string = malloc(b64len); sodium_bin2base64((char *const) b64string, b64len, key, keylen, sodium_base64_VARIANT_ORIGINAL); // generate uppercase version of variable name size_t namelen = strlen(name); char * nameupper = malloc(namelen); for (unsigned int i = 0; i < namelen; i++) { nameupper[i] = toupper((unsigned char) name[i]); } fprintf(f, "%s=%s\n", nameupper, b64string); free(b64string); } void write_key_files(const char *filebase, const char *varname, unsigned char *key, unsigned int keylen) { char header_filename[4096]; char exim_filename[4096]; char raw_filename[4096]; FILE *f; sprintf(header_filename, "%s.h", filebase); sprintf(exim_filename, "%s_exim.conf", filebase); sprintf(raw_filename, "%s.raw", filebase); // open exim config snippet file f = fopen(exim_filename, "w+"); if (f == NULL) { fprintf(stderr, "Unable to open %s for writing", exim_filename); exit(129); } // write key as exim config dump_key_as_exim_config(f, varname, key, keylen); fprintf(stderr, " Wrote »%s«\n", exim_filename); // close exim file fclose(f); // open raw file f = fopen(raw_filename, "w+"); if (f == NULL) { fprintf(stderr, "Unable to open %s for writing", raw_filename); exit(129); } // write key fwrite(key, sizeof(key[0]), keylen, f); fprintf(stderr, " Wrote »%s«\n", raw_filename); // close raw file fclose(f); } void create_cryptobox_keys(const char *filebase, const char *varname) { unsigned char recipient_pk[crypto_box_PUBLICKEYBYTES]; unsigned char recipient_sk[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(recipient_pk, recipient_sk); char pk_filename[4096]; char pk_varname[4096]; char sk_filename[4096]; char sk_varname[4096]; sprintf(pk_filename, "%s_pk", filebase); sprintf(pk_varname, "%s_pk", varname); sprintf(sk_filename, "%s_sk", filebase); sprintf(sk_varname, "%s_sk", varname); write_key_files(pk_filename, pk_varname, recipient_pk, crypto_box_PUBLICKEYBYTES); write_key_files(sk_filename, sk_varname, recipient_sk, crypto_box_SECRETKEYBYTES); } void create_secretbox_key(const char *filebase, const char *varname) { unsigned char key[crypto_secretbox_KEYBYTES]; crypto_secretbox_keygen(key); char key_filename[4096]; char key_varname[4096]; sprintf(key_filename, "%s_secretbox", filebase); sprintf(key_varname, "%s_key", varname); write_key_files(key_filename, key_varname, key, crypto_secretbox_KEYBYTES); } int main(void) { if (sodium_init() < 0) { fputs("Unable to initialize libsodium", stderr); exit(128); } fputs("=== Creating cryptobox key pair ===\n", stderr); create_cryptobox_keys("cryptobox_recipient", "cryptobox_recipient"); exit(EXIT_SUCCESS); }