//returns "c" which is the last index needed to get the last s-values key rmsMgSigStart(const keyM & pk, mgSig & rv, keyV aG, keyV aHP, const int index) { int rows = pk[0].size(); int cols = pk.size(); if (cols < 2) { printf("Error! What is c if cols = 1!"); } int i = 0, j = 0; key c, c_old, c0, L, R, Hi; sc_0(c_old.bytes); vector<ge_dsmp> Ip(rows); rv.ss = keyM(cols, rv.II); unsigned char m2[96]; for (i = 0; i < rows; i++) { memcpy(m2, pk[index][i].bytes, 32); memcpy(m2 + 32, aG[i].bytes, 32); memcpy(m2 + 64, aHP[i].bytes, 32); precomp(Ip[i], rv.II[i]); sc_add(c_old.bytes, c_old.bytes, cn_fast_hash96(m2).bytes); } int oldi = index; i = (index + 1) % cols; while (i != index) { rv.ss[i] = skvGen(rows); sc_0(c.bytes); for (j = 0; j < rows; j++) { addKeys2(L, rv.ss[i][j], c_old, pk[i][j]); hashToPoint(Hi, pk[i][j]); addKeys3(R, rv.ss[i][j], Hi, c_old, Ip[j]); memcpy(m2, pk[i][j].bytes, 32); memcpy(m2 + 32, L.bytes, 32); memcpy(m2 + 64, R.bytes, 32); sc_add(c.bytes, c.bytes, cn_fast_hash96(m2).bytes); } c_old = copy(c); if (i == 0) { c0 = copy(c); } oldi = i; i = (i + 1) % cols; } return c; }
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; }
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); }