/* Create a new onion path. * * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes) * * new_path must be an empty memory location of atleast Onion_Path size. * * return -1 on failure. * return 0 on success. */ int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes) { if (!new_path || !nodes) return -1; encrypt_precompute(nodes[0].public_key, dht->self_secret_key, new_path->shared_key1); memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES); uint8_t random_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t random_secret_key[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(random_public_key, random_secret_key); encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2); memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES); crypto_box_keypair(random_public_key, random_secret_key); encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3); memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES); new_path->ip_port1 = nodes[0].ip_port; new_path->ip_port2 = nodes[1].ip_port; new_path->ip_port3 = nodes[2].ip_port; memcpy(new_path->node_public_key1, nodes[0].public_key, crypto_box_PUBLICKEYBYTES); memcpy(new_path->node_public_key2, nodes[1].public_key, crypto_box_PUBLICKEYBYTES); memcpy(new_path->node_public_key3, nodes[2].public_key, crypto_box_PUBLICKEYBYTES); return 0; }
static void test_hacl_01(void) { int res; /* Creating keypair ALICE... */ crypto_box_keypair(alice_pk, alice_sk); /* Creating keypair BOB... */ crypto_box_keypair(bob_pk, bob_sk); memset(m, 0, crypto_box_ZEROBYTES); memcpy(m + crypto_box_ZEROBYTES, message, MLEN - crypto_box_ZEROBYTES); /* Encrypting using pk_bob... */ crypto_box(c, m, MLEN, n, bob_pk, alice_sk); memset(result, '\0', sizeof(result)); /* Decrypting... */ res = crypto_box_open(result, c, MLEN, n, alice_pk, bob_sk); TEST_ASSERT_EQUAL_INT(0, res); memset(r, 0, sizeof(r)); memcpy(r, result + crypto_box_ZEROBYTES, MLEN - crypto_box_ZEROBYTES); TEST_ASSERT_EQUAL_STRING((const char*)message, (const char*)r); }
int main(void) { size_t mlen; size_t i; int caught; for (mlen = 0;mlen < 1000 && mlen + crypto_box_ZEROBYTES < sizeof m;++mlen) { crypto_box_keypair(alicepk,alicesk); crypto_box_keypair(bobpk,bobsk); randombytes(n,crypto_box_NONCEBYTES); randombytes(m + crypto_box_ZEROBYTES,mlen); crypto_box(c,m,mlen + crypto_box_ZEROBYTES,n,bobpk,alicesk); caught = 0; while (caught < 10) { c[rand() % (mlen + crypto_box_ZEROBYTES)] = rand(); if (crypto_box_open(m2,c,mlen + crypto_box_ZEROBYTES,n,alicepk,bobsk) == 0) { for (i = 0;i < mlen + crypto_box_ZEROBYTES;++i) if (m2[i] != m[i]) { printf("forgery\n"); return 100; } } else { ++caught; } } } return 0; }
int main() { char * padded_message; int padded_mlen; u8 sk[PRIV_KEY_LEN] = {0}; u8 pk[PUB_KEY_LEN] = {0}; u8 sk2[PRIV_KEY_LEN] = {0}; u8 pk2[PUB_KEY_LEN] = {0}; u8 nonce[NONCE_LEN] = {0}; char* message = "This is a cross-platform test of crypto_box/crypto_box_open in TweetNaCl."; u8 * ciphertext; char *decryptedmessage; // randomize nonce randombytes(nonce, NONCE_LEN); printf("Nonce: \n"); hexdump((char*)nonce, NONCE_LEN); crypto_box_keypair(pk, sk); crypto_box_keypair(pk2, sk2); printf("Public key: \n"); hexdump((char*)pk, PUB_KEY_LEN); printf("\nSecret key: \n"); hexdump((char*)sk, PRIV_KEY_LEN); printf("Public key2: \n"); hexdump((char*)pk2, PUB_KEY_LEN); printf("\nSecret key2: \n"); hexdump((char*)sk2, PRIV_KEY_LEN); padded_mlen = strlen(message) + PADDING_LEN; padded_message = (char*) malloc(padded_mlen); memset(padded_message, 0, PADDING_LEN); memcpy(padded_message + PADDING_LEN, message, strlen(message)); ciphertext = (u8*) malloc(padded_mlen); // we have a string so add 1 byte and NUL it so we can print it decryptedmessage = (char*) malloc(padded_mlen+1); decryptedmessage[padded_mlen] = '\0'; printf("crypto_box returned: %d\n",crypto_box(ciphertext, (u8*)padded_message, padded_mlen, nonce, pk2, sk)); free(padded_message); printf("\nCipher text: \n"); hexdump((char*)ciphertext, padded_mlen); printf("crypto_box_open returned: %d\n", crypto_box_open((u8*)decryptedmessage, ciphertext, padded_mlen, nonce, pk, sk2)); free(ciphertext); printf("\nDecrypted text: \n"); hexdump((char*)decryptedmessage, padded_mlen); printf("%s\n", decryptedmessage+32); free(decryptedmessage); return 0; }
/* Start a secure connection with other peer who has public_key and ip_port returns -1 if failure returns crypt_connection_id of the initialized connection if everything went well. */ int crypto_connect(uint8_t *public_key, IP_Port ip_port) { uint32_t i; int id = getcryptconnection_id(public_key); if (id != -1) { IP_Port c_ip = connection_ip(crypto_connections[id].number); if(c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) return -1; } for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { if (crypto_connections[i].status == CONN_NO_CONNECTION) { int id = new_connection(ip_port); if (id == -1) return -1; crypto_connections[i].number = id; crypto_connections[i].status = CONN_HANDSHAKE_SENT; random_nonce(crypto_connections[i].recv_nonce); memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); if (send_cryptohandshake(id, public_key, crypto_connections[i].recv_nonce, crypto_connections[i].sessionpublic_key) == 1) { increment_nonce(crypto_connections[i].recv_nonce); return i; } return -1; /* this should never happen. */ } } return -1; }
int main(int argc,char **argv) { char *d; if (!argv[0]) die_usage(); if (!argv[1]) die_usage(); d = argv[1]; umask(022); if (mkdir(d,0755) == -1) die_fatal("unable to create directory",d,0); if (chdir(d) == -1) die_fatal("unable to chdir to directory",d,0); if (mkdir(".expertsonly",0700) == -1) die_fatal("unable to create directory",d,".expertsonly"); sodium_init(); crypto_box_keypair(pk,sk); create(d,"publickey",pk,sizeof pk); randombytes(noncekey,sizeof noncekey); umask(077); create(d,".expertsonly/secretkey",sk,sizeof sk); create(d,".expertsonly/lock",lock,sizeof lock); create(d,".expertsonly/noncekey",noncekey,sizeof noncekey); create(d,".expertsonly/noncecounter",noncecounter,sizeof noncecounter); return 0; }
PyObject *pycrypto_box_keypair(PyObject *self){ PyObject *pypk, *pysk, *pyret; unsigned char pk[crypto_box_PUBLICKEYBYTES]; unsigned char sk[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(pk, sk); pypk = PyBytes_FromStringAndSize((char *)pk, crypto_box_PUBLICKEYBYTES); if (!pypk) return (PyObject *)0; pysk = PyBytes_FromStringAndSize((char *)sk, crypto_box_SECRETKEYBYTES); if (!pysk){ Py_DECREF(pypk); return (PyObject *)0;} pyret = PyTuple_New(2); if (!pyret){ Py_DECREF(pypk); Py_DECREF(pysk); return (PyObject *)0;} PyTuple_SET_ITEM(pyret, 0, pypk); PyTuple_SET_ITEM(pyret, 1, pysk); return pyret;}
int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key) { #if defined (ZMQ_HAVE_CURVE) # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "CURVE encryption library not built correctly" # endif uint8_t public_key [32]; uint8_t secret_key [32]; int rc = crypto_box_keypair (public_key, secret_key); // Is there a sensible errno to set here? if (rc) return rc; zmq_z85_encode (z85_public_key, public_key, 32); zmq_z85_encode (z85_secret_key, secret_key, 32); return 0; #else (void) z85_public_key, (void) z85_secret_key; errno = ENOTSUP; return -1; #endif }
int zmq_curve_keypair (char *z85_public_key_, char *z85_secret_key_) { #if defined(ZMQ_HAVE_CURVE) #if crypto_box_PUBLICKEYBYTES != 32 || crypto_box_SECRETKEYBYTES != 32 #error "CURVE encryption library not built correctly" #endif uint8_t public_key[32]; uint8_t secret_key[32]; zmq::random_open (); int res = crypto_box_keypair (public_key, secret_key); zmq_z85_encode (z85_public_key_, public_key, 32); zmq_z85_encode (z85_secret_key_, secret_key, 32); zmq::random_close (); return res; #else (void) z85_public_key_, (void) z85_secret_key_; errno = ENOTSUP; return -1; #endif }
/* * encrypt a file using public key cryptography * ephemeral key version that discards sender key pair */ static void ekpubencrypt(const char *pubkeyfile, const char *ident, const char *msgfile, const char *encfile) { struct ekcmsg ekcmsg; struct pubkey pubkey; uint8_t *msg; unsigned long long msglen; uint8_t enckey[ENCSECRETBYTES]; getpubkey(pubkeyfile, ident, &pubkey); crypto_box_keypair(ekcmsg.pubkey, enckey); msg = readall(msgfile, &msglen); memcpy(ekcmsg.ekcalg, EKCALG, 2); memcpy(ekcmsg.pubfingerprint, pubkey.fingerprint, FPLEN); pubencryptmsg(msg, msglen, ekcmsg.box, pubkey.enckey, enckey); explicit_bzero(&enckey, sizeof(enckey)); writeencfile(encfile, &ekcmsg, sizeof(ekcmsg), "<ephemeral>", msg, msglen); xfree(msg, msglen); }
void Connection::handle_request(const CryptoIdentity& ci, const RoutingRequest& rq, const Hop& hop, const std::string& route_id, TransportSocket ts) { if ( hop.type() != Hop::UP ) return; if ( hop.nonce_algo() != Hop::XTEA32 ) return; // response is a "cookie packet": // tag, route id, nonce (24 bytes), [ConnectionAccept](B<>A') std::string cookie_packet; cookie_packet.push_back('\0'); cookie_packet.append(route_id); std::string nonce = randomstring(24); cookie_packet.append(nonce); ConnectionAccept ack; ack.set_auth( ConnectionAccept::AUTHENC_BCARD ); // generate our keys for this connection std::string connection_sk; std::string connection_pk = crypto_box_keypair(&connection_sk); ack.set_sender_pubkey(connection_pk); // ...and let the other party store them for us, in encrypted form ofc ack.set_cookie( ci.cookies.cookie( rq.sender_pubkey() + connection_sk ) ); assert(ack.cookie().size() == COOKIE_SIZE); std::string encpart; ci.encrypt( ack.SerializeAsString() , nonce , static_cast<PkencAlgo>(rq.enc_algo()) , rq.sender_pubkey() , encpart); cookie_packet.append(encpart); ts.send(cookie_packet); }
zmq::curve_client_t::curve_client_t (const options_t &options_) : mechanism_t (options_), state (send_hello), cn_nonce(1), cn_peer_nonce(1), sync() { int rc; memcpy (public_key, options_.curve_public_key, crypto_box_PUBLICKEYBYTES); memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES); memcpy (server_key, options_.curve_server_key, crypto_box_PUBLICKEYBYTES); scoped_lock_t lock (sync); #if defined(HAVE_TWEETNACL) // allow opening of /dev/urandom unsigned char tmpbytes[4]; randombytes(tmpbytes, 4); #else rc = sodium_init (); zmq_assert (rc != -1); #endif // Generate short-term key pair rc = crypto_box_keypair (cn_public, cn_secret); zmq_assert (rc == 0); }
void tunnel_initClient(struct tunnel *t, uint64_t tid, void *serverPublickey) { t->tid = tid; t->state = TUNNEL_STATE_CLIENT_PRE_HANDSHAKE; crypto_box_keypair(t->localPublickey, t->localSecretkey); memcpy(t->remotePublickey, serverPublickey, sizeof t->remotePublickey); memset(t->nonce, 0, sizeof t->nonce); }
int main (void) { #ifdef HAVE_LIBSODIUM # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "libsodium not built correctly" # endif puts ("This tool generates a CurveZMQ keypair, as two printable strings you can"); puts ("use in configuration files or source code. The encoding uses Z85, which"); puts ("is a base-85 format that is described in 0MQ RFC 32, and which has an"); puts ("implementation in the z85_codec.h source used by this tool. The keypair"); puts ("always works with the secret key held by one party and the public key"); puts ("distributed (securely!) to peers wishing to connect to it."); uint8_t public_key [32]; uint8_t secret_key [32]; int rc = crypto_box_keypair (public_key, secret_key); assert (rc == 0); char encoded [41]; zmq_z85_encode (encoded, public_key, 32); puts ("\n== CURVE PUBLIC KEY =="); puts (encoded); zmq_z85_encode (encoded, secret_key, 32); puts ("\n== CURVE SECRET KEY =="); puts (encoded); #else puts ("To build curve_keygen, please install libsodium and then rebuild libzmq."); #endif exit (0); }
int main() { int fd[4], i; byte key_pub [2][pub_len], key_priv[2][priv_len]; /* open files */ for (i=0; i<4; i++) { if ((fd[i] = open(name[i], O_WRONLY|O_CREAT|O_EXCL, (i%2) ? 0400 : 0444)) == -1) { fprintf(stderr, (errno == EEXIST) ? "%s already exists\n" : "could not create file %s\n", name[i]); error_cleanup(i); } } /* generate keys */ for (i=0; i<2; i++) { crypto_box_keypair(key_pub[i], key_priv[i]); if ((write(fd[2*i ], key_pub[i], pub_len) != pub_len) || (write(fd[2*i+1], key_priv[i], priv_len) != priv_len) || (close(fd[2*i ]) == -1) || (close(fd[2*i+1]) == -1)) { error_cleanup(4); } } return 0; }
int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key) { #ifdef HAVE_LIBSODIUM # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "libsodium not built correctly" # endif uint8_t public_key [32]; uint8_t secret_key [32]; int rc = crypto_box_keypair (public_key, secret_key); // Is there a sensible errno to set here? if (rc) return rc; zmq_z85_encode (z85_public_key, public_key, 32); zmq_z85_encode (z85_secret_key, secret_key, 32); return 0; #else // requires libsodium errno = ENOTSUP; return -1; #endif }
zmq::curve_server_t::curve_server_t (session_base_t *session_, const std::string &peer_address_, const options_t &options_) : mechanism_t (options_), session (session_), peer_address (peer_address_), state (expect_hello), expecting_zap_reply (false), cn_nonce (1), sync() { // Fetch our secret key from socket options memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES); scoped_lock_t lock (sync); #if defined(HAVE_TWEETNACL) // allow opening of /dev/urandom unsigned char tmpbytes[4]; randombytes(tmpbytes, 4); #else // todo check return code sodium_init(); #endif // Generate short-term key pair const int rc = crypto_box_keypair (cn_public, cn_secret); zmq_assert (rc == 0); }
/* Add a friend who we want to connect to. * * return -1 on failure. * return the friend number on success or if the friend was already added. */ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id) { int num = onion_friend_num(onion_c, client_id); if (num != -1) return num; uint32_t i, index = ~0; for (i = 0; i < onion_c->num_friends; ++i) { if (onion_c->friends_list[i].status == 0) { index = i; break; } } if (index == (uint32_t)~0) { if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1) return -1; index = onion_c->num_friends; memset(&(onion_c->friends_list[onion_c->num_friends]), 0, sizeof(Onion_Friend)); ++onion_c->num_friends; } onion_c->friends_list[index].status = 1; memcpy(onion_c->friends_list[index].real_client_id, client_id, crypto_box_PUBLICKEYBYTES); crypto_box_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key); return index; }
Onion_Client *new_onion_client(Net_Crypto *c) { if (c == NULL) return NULL; Onion_Client *onion_c = calloc(1, sizeof(Onion_Client)); if (onion_c == NULL) return NULL; if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) { free(onion_c); return NULL; } onion_c->dht = c->dht; onion_c->net = c->dht->net; onion_c->c = c; new_symmetric_key(onion_c->secret_symmetric_key); crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key); networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c); oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c); cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); tcp_onion_response_handler(onion_c->c, &handle_tcp_onion, onion_c); return onion_c; }
int main(int argc, char **argv) { unsigned char pk[crypto_box_PUBLICKEYBYTES]; unsigned char sk[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(pk, sk); return 1; }
static int l_keypair_create(lua_State *l) { void *publickey = lua_newuserdata(l, crypto_box_PUBLICKEYBYTES), *secretkey = lua_newuserdata(l, crypto_box_SECRETKEYBYTES); crypto_box_keypair(publickey, secretkey); return 2; }
/* Accept an incoming connection using the parameters provided by crypto_inbound. * * return -1 if not successful. * return the crypt_connection_id if successful. */ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) { uint32_t i; if (discard_packet(c->lossless_udp, connection_id) == -1) return -1; /* * if(getcryptconnection_id(public_key) != -1) * { * return -1; * } */ if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 || c->crypto_connections == NULL) return -1; memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); c->crypto_connections[c->crypto_connections_length].number = ~0; for (i = 0; i <= c->crypto_connections_length; ++i) { if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { c->crypto_connections[i].number = connection_id; c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; random_nonce(c->crypto_connections[i].recv_nonce); memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); increment_nonce(c->crypto_connections[i].sent_nonce); memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); if (c->crypto_connections_length == i) ++c->crypto_connections_length; if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce, c->crypto_connections[i].sessionpublic_key) == 1) { increment_nonce(c->crypto_connections[i].recv_nonce); uint32_t zero = 0; encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, c->crypto_connections[i].sessionsecret_key, c->crypto_connections[i].shared_key); c->crypto_connections[i].status = CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ return i; } return -1; /* This should never happen. */ } } return -1; }
curve_keypair_t * curve_keypair_new (void) { curve_keypair_t *self = (curve_keypair_t *) zmalloc (sizeof (curve_keypair_t)); assert (self); int rc = crypto_box_keypair (self->public_key, self->secret_key); assert (rc == 0); return self; }
// pk,sk = crypto_box_keypair() static int tweetnacl_crypto_box_keypair( lua_State* L ) { u8 secret_key[crypto_box_SECRETKEYBYTES] = {0}; u8 public_key[crypto_box_PUBLICKEYBYTES] = {0}; crypto_box_keypair(public_key, secret_key); lua_pushlstring(L, public_key, sizeof(public_key)); lua_pushlstring(L, secret_key, sizeof(secret_key)); return 2; }
/// Generate a temporary (non-persistent) key pair WINEXPORT void cryptcurve25519_gen_temp_keypair(const char *key_id) ///< key_id CANNOT be NULL { unsigned char* public_key = g_malloc(crypto_box_PUBLICKEYBYTES); unsigned char* secret_key = g_malloc(crypto_box_SECRETKEYBYTES); crypto_box_keypair(public_key, secret_key); (void) cryptframe_privatekey_new(key_id, secret_key); (void) cryptframe_publickey_new(key_id, public_key); }
int Secure_GenKeys(Secure_PubKey pub, Secure_PrivKey priv) { if(crypto_box_keypair(pub, priv)) { Error_Print("Unable to generate keypair.\n"); return -1; } return 0; }
zmq::curve_client_t::curve_client_t (const options_t &options_) : mechanism_t (options_), state (send_hello) { memcpy (public_key, options_.curve_public_key, crypto_box_PUBLICKEYBYTES); memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES); memcpy (server_key, options_.curve_server_key, crypto_box_PUBLICKEYBYTES); // Generate short-term key pair const int rc = crypto_box_keypair (cn_public, cn_secret); zmq_assert (rc == 0); }
Group_Chat *new_groupchat(Networking_Core *net) { unix_time_update(); if (net == 0) return 0; Group_Chat *chat = calloc(1, sizeof(Group_Chat)); chat->net = net; crypto_box_keypair(chat->self_public_key, chat->self_secret_key); return chat; }
uint8_t cipher_generate(lob_t keys, lob_t secrets) { uint8_t secret[crypto_box_SECRETKEYBYTES], key[crypto_box_PUBLICKEYBYTES]; // create identity keypair crypto_box_keypair(key,secret); lob_set_base32(keys,"3a",key,crypto_box_PUBLICKEYBYTES); lob_set_base32(secrets,"3a",secret,crypto_box_SECRETKEYBYTES); return 0; }
zcert_t * zcert_new (void) { #if defined (HAVE_LIBSODIUM) byte public_key [32] = { 0 }; byte secret_key [32] = { 0 }; int rc = crypto_box_keypair (public_key, secret_key); assert (rc == 0); return zcert_new_from (public_key, secret_key); #else return NULL; #endif }