int main(void) { int i; unsigned char sk[32]; unsigned char pk[32]; crypto_box_seed_keypair(pk, sk, seed); for (i = 0; i < 32; ++i) { printf(",0x%02x", (unsigned int)pk[i]); if (i % 8 == 7) printf("\n"); } for (i = 0; i < 32; ++i) { printf(",0x%02x", (unsigned int)sk[i]); if (i % 8 == 7) printf("\n"); } return 0; }
/* * Create a new set of master keys. * * Seed is optional, can be NULL. It can be of any length and doesn't * require to have high entropy. It will be used as entropy source * in addition to the OSs CPRNG. * * WARNING: Don't use Entropy from the OSs CPRNG as seed! */ return_status master_keys_create( master_keys ** const keys, //output const buffer_t * const seed, buffer_t * const public_signing_key, //output, optional, can be NULL buffer_t * const public_identity_key //output, optional, can be NULL ) { return_status status = return_status_init(); //seeds buffer_t *crypto_seeds = NULL; if (keys == NULL) { throw(INVALID_INPUT, "Invalid input for master_keys_create."); } *keys = sodium_malloc(sizeof(master_keys)); throw_on_failed_alloc(*keys); //initialize the buffers buffer_init_with_pointer((*keys)->public_signing_key, (*keys)->public_signing_key_storage, PUBLIC_MASTER_KEY_SIZE, PUBLIC_MASTER_KEY_SIZE); buffer_init_with_pointer((*keys)->private_signing_key, (*keys)->private_signing_key_storage, PRIVATE_MASTER_KEY_SIZE, PRIVATE_MASTER_KEY_SIZE); buffer_init_with_pointer((*keys)->public_identity_key, (*keys)->public_identity_key_storage, PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE); buffer_init_with_pointer((*keys)->private_identity_key, (*keys)->private_identity_key_storage, PRIVATE_KEY_SIZE, PRIVATE_KEY_SIZE); if (seed != NULL) { //use external seed //create the seed buffer crypto_seeds = buffer_create_with_custom_allocator( crypto_sign_SEEDBYTES + crypto_box_SEEDBYTES, crypto_sign_SEEDBYTES + crypto_box_SEEDBYTES, sodium_malloc, sodium_free); throw_on_failed_alloc(crypto_seeds); status = spiced_random(crypto_seeds, seed, crypto_seeds->buffer_length); throw_on_error(GENERIC_ERROR, "Failed to create spiced random data."); //generate the signing keypair int status_int = 0; status_int = crypto_sign_seed_keypair( (*keys)->public_signing_key->content, (*keys)->private_signing_key_storage, crypto_seeds->content); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate signing keypair."); } //generate the identity keypair status_int = crypto_box_seed_keypair( (*keys)->public_identity_key->content, (*keys)->private_identity_key->content, crypto_seeds->content + crypto_sign_SEEDBYTES); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate encryption keypair."); } } else { //don't use external seed //generate the signing keypair int status_int = 0; status_int = crypto_sign_keypair( (*keys)->public_signing_key->content, (*keys)->private_signing_key->content); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate signing keypair."); } //generate the identity keypair status_int = crypto_box_keypair( (*keys)->public_identity_key->content, (*keys)->private_identity_key->content); if (status_int != 0) { throw(KEYGENERATION_FAILED, "Failed to generate encryption keypair."); } } //copy the public keys if requested if (public_signing_key != NULL) { if (public_signing_key->buffer_length < PUBLIC_MASTER_KEY_SIZE) { public_signing_key->content_length = 0; throw(INCORRECT_BUFFER_SIZE, "Public master key buffer is too short."); } if (buffer_clone(public_signing_key, (*keys)->public_signing_key) != 0) { throw(BUFFER_ERROR, "Failed to copy public signing key."); } } if (public_identity_key != NULL) { if (public_identity_key->buffer_length < PUBLIC_KEY_SIZE) { public_identity_key->content_length = 0; throw(INCORRECT_BUFFER_SIZE, "Public encryption key buffer is too short."); } if (buffer_clone(public_identity_key, (*keys)->public_identity_key) != 0) { throw(BUFFER_ERROR, "Failed to copy public encryption key."); } } cleanup: buffer_destroy_with_custom_deallocator_and_null_if_valid(crypto_seeds, sodium_free); on_error { if (keys != NULL) { sodium_free_and_null_if_valid(*keys); } return status; } if ((keys != NULL) && (*keys != NULL)) { sodium_mprotect_noaccess(*keys); } return status; }