static void test_routerkeys_cross_certify_ntor(void *args) { (void) args; tor_cert_t *cert = NULL; curve25519_keypair_t onion_keys; ed25519_public_key_t master_key; ed25519_public_key_t onion_check_key; time_t now = time(NULL); int sign; tt_int_op(0, OP_EQ, ed25519_public_from_base64(&master_key, "IamwritingthesetestsOnARainyAfternoonin2014")); tt_int_op(0, OP_EQ, curve25519_keypair_generate(&onion_keys, 0)); cert = make_ntor_onion_key_crosscert(&onion_keys, &master_key, now, 10000, &sign); tt_assert(cert); tt_assert(sign == 0 || sign == 1); tt_int_op(cert->cert_type, OP_EQ, CERT_TYPE_ONION_ID); tt_int_op(1, OP_EQ, ed25519_pubkey_eq(&cert->signed_key, &master_key)); tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key( &onion_check_key, &onion_keys.pubkey, sign)); tt_int_op(0, OP_EQ, tor_cert_checksig(cert, &onion_check_key, now)); done: tor_cert_free(cert); }
/** * Given a curve25519 keypair in <b>inp</b>, generate a corresponding * ed25519 keypair in <b>out</b>, and set <b>signbit_out</b> to the * sign bit of the X coordinate of the ed25519 key. * * NOTE THAT IT IS PROBABLY NOT SAFE TO USE THE GENERATED KEY FOR ANYTHING * OUTSIDE OF WHAT'S PRESENTED IN PROPOSAL 228. In particular, it's probably * not a great idea to use it to sign attacker-supplied anything. */ int ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out, int *signbit_out, const curve25519_keypair_t *inp) { const char string[] = "Derive high part of ed25519 key from curve25519 key"; ed25519_public_key_t pubkey_check; SHA512_CTX ctx; uint8_t sha512_output[64]; memcpy(out->seckey.seckey, inp->seckey.secret_key, 32); SHA512_Init(&ctx); SHA512_Update(&ctx, out->seckey.seckey, 32); SHA512_Update(&ctx, string, sizeof(string)); SHA512_Final(sha512_output, &ctx); memcpy(out->seckey.seckey + 32, sha512_output, 32); ed25519_public_key_generate(&out->pubkey, &out->seckey); *signbit_out = out->pubkey.pubkey[31] >> 7; ed25519_public_key_from_curve25519_public_key(&pubkey_check, &inp->pubkey, *signbit_out); tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32)); memwipe(&pubkey_check, 0, sizeof(pubkey_check)); memwipe(&ctx, 0, sizeof(ctx)); memwipe(sha512_output, 0, sizeof(sha512_output)); return 0; }
static void bench_ed25519_impl(void) { uint64_t start, end; const int iters = 1<<12; int i; const uint8_t msg[] = "but leaving, could not tell what they had heard"; ed25519_signature_t sig; ed25519_keypair_t kp; curve25519_keypair_t curve_kp; ed25519_public_key_t pubkey_tmp; ed25519_secret_key_generate(&kp.seckey, 0); start = perftime(); for (i = 0; i < iters; ++i) { ed25519_public_key_generate(&kp.pubkey, &kp.seckey); } end = perftime(); printf("Generate public key: %.2f usec\n", MICROCOUNT(start, end, iters)); start = perftime(); for (i = 0; i < iters; ++i) { ed25519_sign(&sig, msg, sizeof(msg), &kp); } end = perftime(); printf("Sign a short message: %.2f usec\n", MICROCOUNT(start, end, iters)); start = perftime(); for (i = 0; i < iters; ++i) { ed25519_checksig(&sig, msg, sizeof(msg), &kp.pubkey); } end = perftime(); printf("Verify signature: %.2f usec\n", MICROCOUNT(start, end, iters)); curve25519_keypair_generate(&curve_kp, 0); start = perftime(); for (i = 0; i < iters; ++i) { ed25519_public_key_from_curve25519_public_key(&pubkey_tmp, &curve_kp.pubkey, 1); } end = perftime(); printf("Convert public point from curve25519: %.2f usec\n", MICROCOUNT(start, end, iters)); curve25519_keypair_generate(&curve_kp, 0); start = perftime(); for (i = 0; i < iters; ++i) { ed25519_public_blind(&pubkey_tmp, &kp.pubkey, msg); } end = perftime(); printf("Blind a public key: %.2f usec\n", MICROCOUNT(start, end, iters)); }
static void test_crypto_ed25519_fuzz_donna(void *arg) { const unsigned iters = 1024; uint8_t msg[1024]; unsigned i; (void)arg; tt_uint_op(iters, OP_EQ, sizeof(msg)); crypto_rand((char*) msg, sizeof(msg)); /* Fuzz Ed25519-donna vs ref10, alternating the implementation used to * generate keys/sign per iteration. */ for (i = 0; i < iters; ++i) { const int use_donna = i & 1; uint8_t blinding[32]; curve25519_keypair_t ckp; ed25519_keypair_t kp, kp_blind, kp_curve25519; ed25519_public_key_t pk, pk_blind, pk_curve25519; ed25519_signature_t sig, sig_blind; int bit = 0; crypto_rand((char*) blinding, sizeof(blinding)); /* Impl. A: * 1. Generate a keypair. * 2. Blinded the keypair. * 3. Sign a message (unblinded). * 4. Sign a message (blinded). * 5. Generate a curve25519 keypair, and convert it to Ed25519. */ ed25519_set_impl_params(use_donna); tt_int_op(0, OP_EQ, ed25519_keypair_generate(&kp, i&1)); tt_int_op(0, OP_EQ, ed25519_keypair_blind(&kp_blind, &kp, blinding)); tt_int_op(0, OP_EQ, ed25519_sign(&sig, msg, i, &kp)); tt_int_op(0, OP_EQ, ed25519_sign(&sig_blind, msg, i, &kp_blind)); tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ckp, i&1)); tt_int_op(0, OP_EQ, ed25519_keypair_from_curve25519_keypair( &kp_curve25519, &bit, &ckp)); /* Impl. B: * 1. Validate the public key by rederiving it. * 2. Validate the blinded public key by rederiving it. * 3. Validate the unblinded signature (and test a invalid signature). * 4. Validate the blinded signature. * 5. Validate the public key (from Curve25519) by rederiving it. */ ed25519_set_impl_params(!use_donna); tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pk, &kp.seckey)); tt_mem_op(pk.pubkey, OP_EQ, kp.pubkey.pubkey, 32); tt_int_op(0, OP_EQ, ed25519_public_blind(&pk_blind, &kp.pubkey, blinding)); tt_mem_op(pk_blind.pubkey, OP_EQ, kp_blind.pubkey.pubkey, 32); tt_int_op(0, OP_EQ, ed25519_checksig(&sig, msg, i, &pk)); sig.sig[0] ^= 15; tt_int_op(-1, OP_EQ, ed25519_checksig(&sig, msg, sizeof(msg), &pk)); tt_int_op(0, OP_EQ, ed25519_checksig(&sig_blind, msg, i, &pk_blind)); tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key( &pk_curve25519, &ckp.pubkey, bit)); tt_mem_op(pk_curve25519.pubkey, OP_EQ, kp_curve25519.pubkey.pubkey, 32); } done: ; }