void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *epk) { /* generate keypairs from random seed */ byte *ms = urmalloc(32); byte *ss = urmalloc(32); byte *cs = urmalloc(32); /* ed25519 master key */ crypto_sign_seed_keypair(mpk, msk, ms); /* ed25519 signing key */ crypto_sign_seed_keypair(epk, esk, ss); /* curve25519 secret key */ memcpy(csk, cs, 32); csk[0] &= 248; csk[31] &= 63; csk[31] |= 64; /* curve25519 public key */ crypto_scalarmult_curve25519_base(cpk, csk); ucfree(ms, 32); ucfree(ss, 32); ucfree(cs, 32); }
SEXP R_sig_keygen(SEXP seed) { if(LENGTH(seed) != crypto_sign_SEEDBYTES) Rf_error("Invalid seed, must be exactly %d bytes", crypto_sign_SEEDBYTES); SEXP res = allocVector(RAWSXP, crypto_sign_SECRETKEYBYTES); unsigned char pk[crypto_sign_PUBLICKEYBYTES]; if(crypto_sign_seed_keypair(pk, RAW(res), RAW(seed))) Rf_error("keygen failed"); return res; }
// Derives the Ed25519 public key from the stored private key seed. int EdDSA::publicKey(unsigned char* pubKey) { unsigned char privKey[crypto_sign_SECRETKEYBYTES]; int check = crypto_sign_seed_keypair(pubKey, privKey, (const unsigned char*)this->keySeed); sodium_memzero(privKey, sizeof privKey); if (check != 0) { return(0); } return(1); }
int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { unsigned char seed[32]; int ret; randombytes_buf(seed, sizeof seed); ret = crypto_sign_seed_keypair(pk, sk, seed); sodium_memzero(seed, sizeof seed); return ret; }
// Computes the signature of a message. int EdDSA::sign(unsigned char* msg, unsigned long long msglen, unsigned char* sig) { unsigned char pubKey[crypto_sign_PUBLICKEYBYTES]; unsigned char privKey[crypto_sign_SECRETKEYBYTES]; int check; check = crypto_sign_seed_keypair(pubKey, privKey, (const unsigned char*)this->keySeed); if (check != 0) { // Something went wrong deriving keys. return(0); } check = crypto_sign_detached(sig, NULL, msg, msglen, privKey); if (check != 0) { // Something went wrong signing the message. return(0); } return(crypto_sign_BYTES + msglen); }
/* * 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; }