diff --git a/src/common/crypto_serialization.h b/src/common/crypto_serialization.h index a5b5bd6c..0b8bd62e 100644 --- a/src/common/crypto_serialization.h +++ b/src/common/crypto_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2023 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying @@ -115,27 +115,6 @@ namespace crypto END_BOOST_SERIALIZATION() }; - struct CLSAG_GGXG_signature_serialized : public CLSAG_GGXG_signature - { - BEGIN_SERIALIZE_OBJECT() - FIELD(c) - FIELD((std::vector&)(r_g)) - FIELD((std::vector&)(r_x)) - FIELD(K1) - FIELD(K2) - FIELD(K3) - END_SERIALIZE() - - BEGIN_BOOST_SERIALIZATION() - BOOST_SERIALIZE(c) - BOOST_SERIALIZE((std::vector&)(r_g)) - BOOST_SERIALIZE((std::vector&)(r_x)) - BOOST_SERIALIZE(K1) - BOOST_SERIALIZE(K2) - BOOST_SERIALIZE(K3) - END_BOOST_SERIALIZATION() - }; - struct CLSAG_GGXXG_signature_serialized : public CLSAG_GGXXG_signature { BEGIN_SERIALIZE_OBJECT() diff --git a/src/crypto/clsag.cpp b/src/crypto/clsag.cpp index ca51c644..26be2c59 100644 --- a/src/crypto/clsag.cpp +++ b/src/crypto/clsag.cpp @@ -1,9 +1,10 @@ -// Copyright (c) 2022-2023 Zano Project -// Copyright (c) 2022-2023 sowle (val@zano.org, crypto.sowle@gmail.com) +// Copyright (c) 2022-2024 Zano Project +// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com) // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -// This file contains implementation of CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el) +// This file contains implementation of the original d-CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el) +// and the extended d/v-CLSAG version (s.a. https://github.com/hyle-team/docs/blob/master/zano/dv-CLSAG-extension/ by sowle) // #include "clsag.h" //#include "misc_log_ex.h" @@ -51,6 +52,7 @@ namespace crypto } hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); hash input_hash = hsc.calc_hash_no_reduce(); hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_0); @@ -87,10 +89,7 @@ namespace crypto hsc.add_point(alpha * ki_base); scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} - sig.r.clear(); - sig.r.reserve(ring_size); - for(size_t i = 0; i < ring_size; ++i) - sig.r.emplace_back(scalar_t::random()); + sig.r.resize_and_make_random(ring_size); for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) { @@ -137,6 +136,7 @@ namespace crypto } hsc.add_pub_key(pseudo_out_amount_commitment); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); hash input_hash = hsc.calc_hash_no_reduce(); hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_0); @@ -203,8 +203,6 @@ namespace crypto CRYPTO_CHECK_AND_THROW_MES((secret_0_xp * c_point_G).to_public_key() == ring[secret_index].stealth_address, "secret_0_xp mismatch"); CRYPTO_CHECK_AND_THROW_MES( secret_1_f * c_point_G == 8 * point_t(ring[secret_index].amount_commitment) - pseudo_out_amount_commitment, "secret_1_f mismatch"); CRYPTO_CHECK_AND_THROW_MES( secret_2_t * c_point_X == 8 * point_t(ring[secret_index].blinded_asset_id) - pseudo_out_blinded_asset_id, "secret_2_t mismatch"); - //CRYPTO_CHECK_AND_THROW_MES( secret_3_q * c_point_G == 8 * point_t(ring[secret_index].concealing_point), ""); - //CRYPTO_CHECK_AND_THROW_MES( secret_4_x * c_point_X == extended_amount_commitment - 8 * point_t(ring[secret_index].amount_commitment) - 8 * point_t(ring[secret_index].concealing_point), ""); #endif point_t K1_div8 = (c_scalar_1div8 * secret_1_f) * ki_base; @@ -217,16 +215,6 @@ namespace crypto point_t K2 = K2_div8; K2.modify_mul8(); - //point_t K3_div8 = (c_scalar_1div8 * secret_3_q) * ki_base; - //K3_div8.to_public_key(sig.K3); - //point_t K3 = K3_div8; - //K3.modify_mul8(); - - //point_t K4_div8 = (c_scalar_1div8 * secret_4_x) * ki_base; - //K4_div8.to_public_key(sig.K4); - //point_t K4 = K4_div8; - //K4.modify_mul8(); - // calculate aggregation coefficients hash_helper_t::hs_t hsc(4 + 3 * ring_size); hsc.add_scalar(m); @@ -240,6 +228,8 @@ namespace crypto hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment); hsc.add_point(c_scalar_1div8 * pseudo_out_blinded_asset_id); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); hash input_hash = hsc.calc_hash_no_reduce(); DBG_VAL_PRINT(input_hash); @@ -259,11 +249,6 @@ namespace crypto scalar_t agg_coeff_2 = hsc.calc_hash(); DBG_VAL_PRINT(agg_coeff_2); - //hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_3); - //hsc.add_hash(input_hash); - //scalar_t agg_coeff_3 = hsc.calc_hash(); - //DBG_VAL_PRINT(agg_coeff_3); - // prepare A_i, Q_i std::vector A_i, Q_i; A_i.reserve(ring_size), Q_i.reserve(ring_size); @@ -300,18 +285,17 @@ namespace crypto } // aggregate secret key (layers 0, 1; G component) - scalar_t w_sec_key_g = agg_coeff_0 * secret_0_xp + agg_coeff_1 * secret_1_f; // + agg_coeff_3 * secret_3_q; + scalar_t w_sec_key_g = agg_coeff_0 * secret_0_xp + agg_coeff_1 * secret_1_f; DBG_VAL_PRINT(w_sec_key_g * c_point_G); // aggregate secret key (layer 2; X component) scalar_t w_sec_key_x = agg_coeff_2 * secret_2_t; DBG_VAL_PRINT(w_sec_key_x * c_point_X); - // calculate aggregate key image (layers 0, 1, 3; G component) - point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 /* + agg_coeff_3 * K3 */; + // calculate aggregate key image (layers 0, 1; G component) + point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1; DBG_VAL_PRINT(key_image); DBG_VAL_PRINT(K1); - //DBG_VAL_PRINT(K3); DBG_VAL_PRINT(W_key_image_g); // calculate aggregate key image (layer 2; X component) @@ -338,15 +322,8 @@ namespace crypto //DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")"); scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} - sig.r_g.clear(); - sig.r_x.clear(); - sig.r_g.reserve(ring_size); - sig.r_x.reserve(ring_size); - for(size_t i = 0; i < ring_size; ++i) - { - sig.r_g.emplace_back(scalar_t::random()); - sig.r_x.emplace_back(scalar_t::random()); - } + sig.r_g.resize_and_make_random(ring_size); + sig.r_x.resize_and_make_random(ring_size); for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) { @@ -403,6 +380,8 @@ namespace crypto hsc.add_pub_key(pseudo_out_amount_commitment); hsc.add_pub_key(pseudo_out_blinded_asset_id); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); hash input_hash = hsc.calc_hash_no_reduce(); DBG_VAL_PRINT(input_hash); @@ -422,11 +401,6 @@ namespace crypto scalar_t agg_coeff_2 = hsc.calc_hash(); DBG_VAL_PRINT(agg_coeff_2); - //hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_3); - //hsc.add_hash(input_hash); - //scalar_t agg_coeff_3 = hsc.calc_hash(); - //DBG_VAL_PRINT(agg_coeff_3); - // prepare A_i, Q_i std::vector A_i, Q_i; A_i.reserve(ring_size), Q_i.reserve(ring_size); @@ -462,13 +436,11 @@ namespace crypto DBG_VAL_PRINT(W_pub_keys_x[i]); } - // calculate aggregate key image (layers 0, 1, 3; G components) + // calculate aggregate key image (layers 0, 1; G components) point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * point_t(sig.K1).modify_mul8(); - // agg_coeff_3 * point_t(sig.K3).modify_mul8(); DBG_VAL_PRINT(point_t(sig.K1).modify_mul8()); - //DBG_VAL_PRINT(point_t(sig.K3).modify_mul8()); DBG_VAL_PRINT(W_key_image_g); // calculate aggregate key image (layer 2; X component) @@ -498,7 +470,7 @@ namespace crypto //--------------------------------------------------------------- - + /* bool generate_CLSAG_GGXG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& extended_amount_commitment, const key_image& ki, const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_x, const scalar_t& secret_3_q, uint64_t secret_index, CLSAG_GGXG_signature& sig) @@ -548,6 +520,9 @@ namespace crypto hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment); hsc.add_point(c_scalar_1div8 * extended_amount_commitment); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); hash input_hash = hsc.calc_hash_no_reduce(); DBG_VAL_PRINT(input_hash); @@ -617,7 +592,7 @@ namespace crypto DBG_VAL_PRINT(w_sec_key_x * c_point_X); // calculate aggregate key image (layers 0, 1, 3; G component) - point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 + /*agg_coeff_2 * K2 +*/ agg_coeff_3 * K3; + point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 + agg_coeff_3 * K3; DBG_VAL_PRINT(key_image); DBG_VAL_PRINT(K1); DBG_VAL_PRINT(K3); @@ -647,15 +622,8 @@ namespace crypto //DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")"); scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} - sig.r_g.clear(); - sig.r_x.clear(); - sig.r_g.reserve(ring_size); - sig.r_x.reserve(ring_size); - for(size_t i = 0; i < ring_size; ++i) - { - sig.r_g.emplace_back(scalar_t::random()); - sig.r_x.emplace_back(scalar_t::random()); - } + sig.r_g.resize_and_make_random(ring_size); + sig.r_x.resize_and_make_random(ring_size); for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) { @@ -713,6 +681,9 @@ namespace crypto hsc.add_pub_key(pseudo_out_amount_commitment); hsc.add_pub_key(extended_amount_commitment); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); hash input_hash = hsc.calc_hash_no_reduce(); DBG_VAL_PRINT(input_hash); @@ -807,7 +778,7 @@ namespace crypto return c_prev == sig.c; } - + */ //--------------------------------------------------------------- @@ -868,6 +839,10 @@ namespace crypto hsc.add_point(c_scalar_1div8 * pseudo_out_blinded_asset_id); hsc.add_point(c_scalar_1div8 * extended_amount_commitment); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); + hsc.add_pub_key(sig.K4); hash input_hash = hsc.calc_hash_no_reduce(); DBG_VAL_PRINT(input_hash); @@ -976,15 +951,8 @@ namespace crypto //DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")"); scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} - sig.r_g.clear(); - sig.r_x.clear(); - sig.r_g.reserve(ring_size); - sig.r_x.reserve(ring_size); - for(size_t i = 0; i < ring_size; ++i) - { - sig.r_g.emplace_back(scalar_t::random()); - sig.r_x.emplace_back(scalar_t::random()); - } + sig.r_g.resize_and_make_random(ring_size); + sig.r_x.resize_and_make_random(ring_size); for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) { @@ -1048,6 +1016,10 @@ namespace crypto hsc.add_pub_key(pseudo_out_blinded_asset_id); hsc.add_pub_key(extended_amount_commitment); hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); + hsc.add_pub_key(sig.K4); hash input_hash = hsc.calc_hash_no_reduce(); DBG_VAL_PRINT(input_hash); diff --git a/src/crypto/clsag.h b/src/crypto/clsag.h index 576ba917..da969d8a 100644 --- a/src/crypto/clsag.h +++ b/src/crypto/clsag.h @@ -1,9 +1,10 @@ -// Copyright (c) 2022-2023 Zano Project -// Copyright (c) 2022-2023 sowle (val@zano.org, crypto.sowle@gmail.com) +// Copyright (c) 2022-2024 Zano Project +// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com) // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -// This file contains implementation of CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el) +// This file contains implementation of the original d-CLSAG (s.a. https://eprint.iacr.org/2019/654.pdf by Goodel at el) +// and the extended d/v-CLSAG version (s.a. https://github.com/hyle-team/docs/blob/master/zano/dv-CLSAG-extension/ by sowle) // #pragma once #include "crypto-sugar.h" @@ -57,11 +58,11 @@ namespace crypto // - // 3-CLSAG + // 3/2-CLSAG // - // 3-CLSAG signature (with respect to the group element G, G, X -- that's why 'GGX') + // 3/2-CLSAG signature (with respect to the group element G, G, X -- that's why 'GGX') struct CLSAG_GGX_signature { scalar_t c; @@ -93,12 +94,13 @@ namespace crypto const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig); + /* // - // 4-CLSAG + // 4/2-CLSAG (eventually, it's not used in Zano) // - // 4-CLSAG signature (with respect to the group element G, G, X, G -- that's why 'GGXG') + // 4/2-CLSAG signature (with respect to the group element G, G, X, G -- that's why 'GGXG') struct CLSAG_GGXG_signature { scalar_t c; @@ -130,14 +132,14 @@ namespace crypto bool verify_CLSAG_GGXG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, const public_key& extended_amount_commitment, const key_image& ki, const CLSAG_GGXG_signature& sig); - + */ // - // 5-CLSAG + // 5/2-CLSAG // - // 5-CLSAG signature (with respect to the group element G, G, X, X, G -- that's why 'GGXXG') + // 5/2-CLSAG signature (with respect to the group element G, G, X, X, G -- that's why 'GGXXG') struct CLSAG_GGXXG_signature { scalar_t c; diff --git a/tests/functional_tests/crypto_tests_clsag.h b/tests/functional_tests/crypto_tests_clsag.h index 372b3968..96897e05 100644 --- a/tests/functional_tests/crypto_tests_clsag.h +++ b/tests/functional_tests/crypto_tests_clsag.h @@ -1,5 +1,5 @@ -// Copyright (c) 2022 Zano Project (https://zano.org/) -// Copyright (c) 2022 sowle (val@zano.org, crypto.sowle@gmail.com) +// Copyright (c) 2022-2024 Zano Project (https://zano.org/) +// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com) // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once @@ -166,11 +166,11 @@ TEST(clsag, bad_pub_keys) ASSERT_TRUE(cc.generate()); ASSERT_TRUE(cc.verify()); - // torsion component in K1 should not affect protocol + // torsion component in K1 should break the protocol cc = cc_orig; ASSERT_TRUE(cc.generate()); cc.sig.K1 = (point_t(cc.sig.K1) + tor).to_public_key(); - ASSERT_TRUE(cc.verify()); + ASSERT_FALSE(cc.verify()); // torsion component in stealth_address for secret_index (i.e. for P = xG) must break the protocol // 1 @@ -399,9 +399,9 @@ TEST(clsag_ggx, basics) /////////////////////////////////////////////////////////////////////////////////////////////////// // -// CLSAG GGXG +// CLSAG GGXG (eventually not used in Zano) // - +/* struct clsag_ggxg_sig_check_t { crypto::hash prefix_hash; @@ -537,7 +537,7 @@ TEST(clsag_ggxg, basics) ASSERT_TRUE(cc.verify()); return true; -} +}*/ /////////////////////////////////////////////////////////////////////////////////////////////////// //