diff --git a/src/crypto/clsag.cpp b/src/crypto/clsag.cpp index 904f0154..ca51c644 100644 --- a/src/crypto/clsag.cpp +++ b/src/crypto/clsag.cpp @@ -998,7 +998,7 @@ namespace crypto hsc.add_point(sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i]); hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); c_prev = hsc.calc_hash(); // c_{i + 1} - DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); + //DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); } DBG_PRINT("c[" << secret_index << "] = " << c_prev); @@ -1141,7 +1141,7 @@ namespace crypto DBG_PRINT("c[0] = " << c_prev); for(size_t i = 0; i < ring_size; ++i) { - hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_CHALLENGE); + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_CHALLENGE); hsc.add_hash(input_hash); hsc.add_point(sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i]); hsc.add_point(sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g); @@ -1149,7 +1149,7 @@ namespace crypto hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); c_prev = hsc.calc_hash(); // c_{i + 1} DBG_PRINT("c[" << i + 1 << "] = " << c_prev); - DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); + //DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); } return c_prev == sig.c; diff --git a/tests/functional_tests/crypto_tests_clsag.h b/tests/functional_tests/crypto_tests_clsag.h index 92623ad5..372b3968 100644 --- a/tests/functional_tests/crypto_tests_clsag.h +++ b/tests/functional_tests/crypto_tests_clsag.h @@ -537,4 +537,157 @@ TEST(clsag_ggxg, basics) ASSERT_TRUE(cc.verify()); return true; -} \ No newline at end of file +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// +// CLSAG GGXXG +// + +struct clsag_ggxxg_sig_check_t +{ + crypto::hash prefix_hash; + crypto::key_image ki; + std::vector stealth_addresses; + std::vector amount_commitments; // div 8 + std::vector blinded_asset_ids; // div 8 + std::vector concealing_points; // div 8 + std::vector ring; + crypto::public_key pseudo_output_commitment; // div 8 + crypto::public_key pseudo_out_blinded_asset_id; // div 8 + crypto::public_key extended_amount_commitment; // div 8 + scalar_t secret_xp; + scalar_t secret_f; // = f - f' = amount_blinding_mask - pseudo_commitment_blinding_mask + scalar_t secret_t; + scalar_t secret_x; + scalar_t secret_q; + size_t secret_index; + CLSAG_GGXXG_signature sig; + + clsag_ggxxg_sig_check_t() + {} + + void rebuild_ring() + { + ring.clear(); + ring.reserve(stealth_addresses.size()); + for(size_t i = 0; i < stealth_addresses.size(); ++i) + ring.emplace_back(stealth_addresses[i], amount_commitments[i], blinded_asset_ids[i], concealing_points[i]); + } + + clsag_ggxxg_sig_check_t& operator=(const clsag_ggxxg_sig_check_t& rhs) + { + prefix_hash = rhs.prefix_hash; + ki = rhs.ki; + stealth_addresses = rhs.stealth_addresses; + amount_commitments = rhs.amount_commitments; + blinded_asset_ids = rhs.blinded_asset_ids; + concealing_points = rhs.concealing_points; + rebuild_ring(); + pseudo_output_commitment = rhs.pseudo_output_commitment; + pseudo_out_blinded_asset_id = rhs.pseudo_out_blinded_asset_id; + extended_amount_commitment = rhs.extended_amount_commitment; + secret_xp = rhs.secret_xp; + secret_f = rhs.secret_f; + secret_t = rhs.secret_t; + secret_x = rhs.secret_x; + secret_q = rhs.secret_q; + secret_index = rhs.secret_index; + return *this; + } + + void prepare_random_data(size_t ring_size) + { + stealth_addresses.clear(); + amount_commitments.clear(); + blinded_asset_ids.clear(); + concealing_points.clear(); + ring.clear(); + + crypto::generate_random_bytes(sizeof prefix_hash, &prefix_hash); + + stealth_addresses.reserve(ring_size); + amount_commitments.reserve(ring_size); + blinded_asset_ids.reserve(ring_size); + concealing_points.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + stealth_addresses.push_back(hash_helper_t::hp(scalar_t::random()).to_public_key()); + amount_commitments.push_back(hash_helper_t::hp(scalar_t::random()).to_public_key()); // div 8 + blinded_asset_ids.push_back(hash_helper_t::hp(scalar_t::random()).to_public_key()); // div 8 + concealing_points.push_back(hash_helper_t::hp(scalar_t::random()).to_public_key()); // div 8 + ring.emplace_back(stealth_addresses.back(), amount_commitments.back(), blinded_asset_ids.back(), concealing_points.back()); + } + + secret_xp = scalar_t::random(); + secret_f = scalar_t::random(); + secret_t = scalar_t::random(); + secret_x = scalar_t::random(); + secret_q = scalar_t::random(); + secret_index = random_in_range(0, ring_size - 1); + + stealth_addresses[secret_index] = (secret_xp * c_point_G).to_public_key(); + concealing_points[secret_index] = (c_scalar_1div8 * secret_q * c_point_G).to_public_key(); + ki = (secret_xp * hash_helper_t::hp(stealth_addresses[secret_index])).to_key_image(); + + pseudo_output_commitment = (point_t(amount_commitments[secret_index]) - c_scalar_1div8 * secret_f * c_point_G).to_public_key(); + pseudo_out_blinded_asset_id = (point_t(blinded_asset_ids[secret_index]) - c_scalar_1div8 * secret_t * c_point_X).to_public_key(); + extended_amount_commitment = (c_scalar_1div8 * secret_x * c_point_X + point_t(amount_commitments[secret_index]) + point_t(concealing_points[secret_index])).to_public_key(); + } + + bool generate() + { + try + { + return generate_CLSAG_GGXXG(prefix_hash, ring, point_t(pseudo_output_commitment).modify_mul8(), point_t(pseudo_out_blinded_asset_id).modify_mul8(), point_t(extended_amount_commitment).modify_mul8(), ki, + secret_xp, secret_f, secret_t, secret_x, secret_q, secret_index, sig); + } + catch(std::exception& e) + { + LOG_PRINT_RED(ENDL << "EXCEPTION: " << e.what(), LOG_LEVEL_0); + return false; + } + } + + bool verify() + { + try + { + return verify_CLSAG_GGXXG(prefix_hash, ring, pseudo_output_commitment, pseudo_out_blinded_asset_id, extended_amount_commitment, ki, sig); + } + catch(std::exception& e) + { + LOG_PRINT_RED(ENDL << "EXCEPTION: " << e.what(), LOG_LEVEL_0); + return false; + } + } +}; + + +TEST(clsag_ggxxg, basics) +{ + std::string X_hash_str("X_generator"); + point_t X = hash_helper_t::hp(X_hash_str.c_str(), X_hash_str.size()); + LOG_PRINT_L0("X = " << X.to_hex_comma_separated_uint64_str()); + ASSERT_EQ(X, c_point_X); + + clsag_ggxxg_sig_check_t cc; + + cc.prepare_random_data(1); + ASSERT_TRUE(cc.generate()); + ASSERT_TRUE(cc.verify()); + + cc.prepare_random_data(2); + ASSERT_TRUE(cc.generate()); + ASSERT_TRUE(cc.verify()); + + cc.prepare_random_data(8); + ASSERT_TRUE(cc.generate()); + ASSERT_TRUE(cc.verify()); + + cc.prepare_random_data(123); + ASSERT_TRUE(cc.generate()); + ASSERT_TRUE(cc.verify()); + + return true; +}