//subtract Keys (subtracts curve points) //AB = A - B where A, B are curve points void subKeys(key & AB, const key &A, const key &B) { ge_p3 B2, A2; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_cached tmp2; ge_p3_to_cached(&tmp2, &B2); ge_p1p1 tmp3; ge_sub(&tmp3, &A2, &tmp2); ge_p1p1_to_p3(&A2, &tmp3); ge_p3_tobytes(AB.bytes, &A2); }
//addKeys3 //aAbB = a*A + b*B where a, b are scalars, A, B are curve points //B must be input after applying "precomp" void addKeys3(key &aAbB, const key &a, const key &A, const key &b, const ge_dsmp B) { ge_p2 rv; ge_p3 A2; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_double_scalarmult_precomp_vartime(&rv, a.bytes, &A2, b.bytes, B); ge_tobytes(aAbB.bytes, &rv); }
//addKeys2 //aGbB = aG + bB where a, b are scalars, G is the basepoint and B is a point void addKeys2(key &aGbB, const key &a, const key &b, const key & B) { ge_p2 rv; ge_p3 B2; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_double_scalarmult_base_vartime(&rv, b.bytes, &B2, a.bytes); ge_tobytes(aGbB.bytes, &rv); }
//does a * P where a is a scalar and P is an arbitrary point void scalarmultKey(key & aP, const key &P, const key &a) { ge_p3 A; ge_p2 R; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_scalarmult(&R, a.bytes, &A); ge_tobytes(aP.bytes, &R); }
//Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint key scalarmultH(const key & a) { ge_p3 A; ge_p2 R; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A, H.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_scalarmult(&R, a.bytes, &A); key aP; ge_tobytes(aP.bytes, &R); return aP; }
static void corrupt_bob_step2(secure_comparator_t *bob, const void *input, size_t input_length, void *output, size_t *output_length) { /* Let's assume bob is malicious and uses zeroes instead of random numbers */ ge_p3 g2a; ge_p3 g3a; ge_p3 g2b; ge_p3 g3b; ge_frombytes_vartime(&g2a, (const unsigned char *)input); ge_frombytes_vartime(&g3a, ((const unsigned char *)input) + (3 * ED25519_GE_LENGTH)); if (THEMIS_SCOMPARE_SEND_OUTPUT_TO_PEER != secure_comparator_proceed_compare(bob, input, input_length, output, output_length)) { testsuite_fail_if(true, "secure_comparator_proceed_compare failed"); return; } memset(bob->rand2, 0, sizeof(bob->rand2)); memset(bob->rand3, 0, sizeof(bob->rand3)); ge_scalarmult_base(&g2b, bob->rand2); ge_scalarmult_base(&g3b, bob->rand3); ge_scalarmult_blinded(&(bob->g2), bob->rand2, &g2a); ge_scalarmult_blinded(&(bob->g3), bob->rand3, &g3a); memset(bob->rand, 0, sizeof(bob->rand)); ge_scalarmult_blinded(&(bob->P), bob->rand, &(bob->g3)); ge_double_scalarmult_vartime((ge_p2 *)&(bob->Q), bob->secret, &(bob->g2), bob->rand); ge_p2_to_p3(&(bob->Q), (const ge_p2 *)&(bob->Q)); ge_p3_tobytes((unsigned char *)output, &g2b); ed_sign(3, bob->rand2, ((unsigned char *)output) + ED25519_GE_LENGTH); ge_p3_tobytes(((unsigned char *)output) + (3 * ED25519_GE_LENGTH), &g3b); ed_sign(4, bob->rand3, ((unsigned char *)output) + (4 * ED25519_GE_LENGTH)); ge_p3_tobytes(((unsigned char *)output) + (6 * ED25519_GE_LENGTH), &(bob->P)); ge_p3_tobytes(((unsigned char *)output) + (7 * ED25519_GE_LENGTH), &(bob->Q)); ed_dbl_base_sign(5, bob->rand, bob->secret, &(bob->g2), &(bob->g3), ((unsigned char *)output) + (8 * ED25519_GE_LENGTH)); }
bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, size_t pubs_count, const signature *sig) { size_t i; ge_p3 image_unp; ge_dsmp image_pre; ec_scalar sum, h; rs_comm *const buf = reinterpret_cast<rs_comm *>(alloca(rs_comm_size(pubs_count))); #if !defined(NDEBUG) for (i = 0; i < pubs_count; i++) { assert(check_key(*pubs[i])); } #endif if (ge_frombytes_vartime(&image_unp, &image) != 0) { return false; } ge_dsm_precomp(image_pre, &image_unp); sc_0(&sum); buf->h = prefix_hash; for (i = 0; i < pubs_count; i++) { ge_p2 tmp2; ge_p3 tmp3; if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) { return false; } if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { abort(); } ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); ge_tobytes(&buf->ab[i].a, &tmp2); hash_to_ec(*pubs[i], tmp3); ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); ge_tobytes(&buf->ab[i].b, &tmp2); sc_add(&sum, &sum, &sig[i].c); } hash_to_scalar(buf, rs_comm_size(pubs_count), h); sc_sub(&h, &h, &sum); return sc_isnonzero(&h) == 0; }
key hashToPointSimple(const key & hh) { key pointk; ge_p1p1 point2; ge_p2 point; ge_p3 res; key h = cn_fast_hash(hh); CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&res, h.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_p3_to_p2(&point, &res); ge_mul8(&point2, &point); ge_p1p1_to_p3(&res, &point2); ge_p3_tobytes(pointk.bytes, &res); return pointk; }
bool crypto_ops::generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { ge_p3 point; ge_p2 point2; ge_p1p1 point3; assert(sc_check(&key2) == 0); if (ge_frombytes_vartime(&point, &key1) != 0) { return false; } ge_scalarmult(&point2, &key2, &point); ge_mul8(&point3, &point2); ge_p1p1_to_p2(&point2, &point3); ge_tobytes(&derivation, &point2); return true; }
bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index, const public_key &base, public_key &derived_key) { ec_scalar scalar; ge_p3 point1; ge_p3 point2; ge_cached point3; ge_p1p1 point4; ge_p2 point5; if (ge_frombytes_vartime(&point1, &base) != 0) { return false; } derivation_to_scalar(derivation, output_index, scalar); ge_scalarmult_base(&point2, &scalar); ge_p3_to_cached(&point3, &point2); ge_add(&point4, &point1, &point3); ge_p1p1_to_p2(&point5, &point4); ge_tobytes(&derived_key, &point5); return true; }
bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { ge_p2 tmp2; ge_p3 tmp3; ec_scalar c; s_comm buf; assert(check_key(pub)); buf.h = prefix_hash; buf.key = pub; if (ge_frombytes_vartime(&tmp3, &pub) != 0) { abort(); } if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) { return false; } ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r); ge_tobytes(&buf.comm, &tmp2); hash_to_scalar(&buf, sizeof(s_comm), c); sc_sub(&c, &c, &sig.c); return sc_isnonzero(&c) == 0; }
bool crypto_ops::check_key(const public_key &key) { ge_p3 point; return ge_frombytes_vartime(&point, &key) == 0; }
void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, size_t pubs_count, const secret_key &sec, size_t sec_index, signature *sig) { lock_guard<mutex> lock(random_lock); size_t i; ge_p3 image_unp; ge_dsmp image_pre; ec_scalar sum, k, h; rs_comm *const buf = reinterpret_cast<rs_comm *>(alloca(rs_comm_size(pubs_count))); assert(sec_index < pubs_count); #if !defined(NDEBUG) { ge_p3 t; public_key t2; key_image t3; assert(sc_check(&sec) == 0); ge_scalarmult_base(&t, &sec); ge_p3_tobytes(&t2, &t); assert(*pubs[sec_index] == t2); generate_key_image(*pubs[sec_index], sec, t3); assert(image == t3); for (i = 0; i < pubs_count; i++) { assert(check_key(*pubs[i])); } } #endif if (ge_frombytes_vartime(&image_unp, &image) != 0) { abort(); } ge_dsm_precomp(image_pre, &image_unp); sc_0(&sum); buf->h = prefix_hash; for (i = 0; i < pubs_count; i++) { ge_p2 tmp2; ge_p3 tmp3; if (i == sec_index) { random_scalar(k); ge_scalarmult_base(&tmp3, &k); ge_p3_tobytes(&buf->ab[i].a, &tmp3); hash_to_ec(*pubs[i], tmp3); ge_scalarmult(&tmp2, &k, &tmp3); ge_tobytes(&buf->ab[i].b, &tmp2); } else { random_scalar(sig[i].c); random_scalar(sig[i].r); if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { abort(); } ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); ge_tobytes(&buf->ab[i].a, &tmp2); hash_to_ec(*pubs[i], tmp3); ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); ge_tobytes(&buf->ab[i].b, &tmp2); sc_add(&sum, &sum, &sig[i].c); } } hash_to_scalar(buf, rs_comm_size(pubs_count), h); sc_sub(&sig[sec_index].c, &h, &sum); sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &sec, &k); }
//Does some precomputation to make addKeys3 more efficient // input B a curve point and output a ge_dsmp which has precomputation applied void precomp(ge_dsmp rv, const key & B) { ge_p3 B2; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__)); ge_dsm_precomp(rv, &B2); }