crypto: CLSAG: auxiliary key images added to the input hash + code cleanup + minor improvements + tests

This commit is contained in:
sowle 2024-01-28 15:44:56 +01:00
parent 90e1b6dc2a
commit 92f09f424f
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
4 changed files with 58 additions and 105 deletions

View file

@ -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<scalar_t>&)(r_g))
FIELD((std::vector<scalar_t>&)(r_x))
FIELD(K1)
FIELD(K2)
FIELD(K3)
END_SERIALIZE()
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(c)
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_g))
BOOST_SERIALIZE((std::vector<scalar_t>&)(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()

View file

@ -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<point_t> 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<point_t> 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<CLSAG_GGXG_input_ref_t>& 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);

View file

@ -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<CLSAG_GGXG_input_ref_t>& 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;

View file

@ -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;
}
}*/
///////////////////////////////////////////////////////////////////////////////////////////////////
//