1
0
Fork 0
forked from lthn/blockchain

experimental crypto: ml2s_lnk_sig_verif implemented completely

This commit is contained in:
sowle 2021-01-26 23:19:26 +03:00
parent 5843f6964c
commit dd095f205c
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC

View file

@ -40,8 +40,8 @@ struct ml2s_signature_element
point_t T0;
scalar_t t0;
point_t Z;
std::vector<scalar_t> r_array;
std::vector<point_t> H_array;
std::vector<scalar_t> r_array; // size = n
std::vector<point_t> H_array; // size = n
point_t T;
scalar_t t;
};
@ -49,11 +49,38 @@ struct ml2s_signature_element
struct ml2s_signature
{
scalar_t z;
std::vector<ml2s_signature_element> elements;
std::vector<ml2s_signature_element> elements; // size = L
};
// reference: mL2SLnkSig_Verif()
bool ml2s_lnk_sig_verif(const scalar_t& m, const std::vector<point_t>& B_array, const ml2s_signature& signature, uint8_t* p_err = nullptr)
size_t log2sz(size_t x)
{
size_t r = 0;
while (x > 1)
x >>= 1, ++r;
return r;
}
template<typename T>
T invert_last_bit(T v)
{
return v ^ 1;
}
template<typename T>
bool is_power_of_2(T v)
{
while (v > 1)
{
if (v & 1)
return false;
v <<= 1;
}
return true;
}
bool ml2s_lnk_sig_verif(const scalar_t& m, const std::vector<point_t>& B_array, const ml2s_signature& signature, uint8_t* p_err = nullptr,
std::vector<point_t>* p_I_array = nullptr)
{
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
if (!(cond)) { LOG_PRINT_RED("ml2s_lnk_sig_verif: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
@ -68,25 +95,25 @@ bool ml2s_lnk_sig_verif(const scalar_t& m, const std::vector<point_t>& B_array,
size_t N = (size_t)1 << n;
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(B_array.size() == N / 2, 5);
std::vector<point_t> I_array(L);
std::vector<point_t> local_I_array;
if (p_I_array == nullptr)
p_I_array = &local_I_array;
p_I_array->resize(L);
std::vector<point_t> A_array(L);
for (size_t i = 0; i < L; ++i)
{
I_array[i] = (signature.elements[i].Z0 - c_point_G) / signature.z;
(*p_I_array)[i] = (signature.elements[i].Z0 - c_point_G) / signature.z;
A_array[i] = signature.elements[i].Z0;
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(signature.elements[i].r_array.size() == n, 1);
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(signature.elements[i].H_array.size() == n, 2);
}
scalar_t z_ = hash_helper_t::hs(m, B_array, I_array);
scalar_t z_ = hash_helper_t::hs(m, B_array, *p_I_array);
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(z_ == signature.z, 3);
scalar_t e = hash_helper_t::hs(signature.z);
// ref: mL2SHPoM_Verif()
// ref: X = mL2SHPoM_GetDecoySet(N, A, hash_point_cb, preimage_set_gen_cb)
std::vector<point_t> P_array(B_array.size());
for (size_t i = 0; i < B_array.size(); ++i)
P_array[i] = hash_point_lambda(B_array[i]);
@ -95,7 +122,7 @@ bool ml2s_lnk_sig_verif(const scalar_t& m, const std::vector<point_t>& B_array,
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(P_array.size() * 2 == N, 6);
std::vector<point_t> X_array(N);
// X_array = { P_array[0], Q_array[0], P_array[1], Q_array[1], etc.
// X_array = { P_array[0], Q_array[0], P_array[1], Q_array[1], etc. }
for (size_t i = 0; i < N; ++i)
{
if (i % 2 == 0)
@ -104,7 +131,89 @@ bool ml2s_lnk_sig_verif(const scalar_t& m, const std::vector<point_t>& B_array,
X_array[i] = hash_point_lambda(Q_shift + B_array[i / 2]);
}
// challenge c0
hash_helper_t::hs_t hs_calculator;
hs_calculator.reserve(1 + N + 3 * L);
hs_calculator.add_scalar(e);
hs_calculator.add_points_array(X_array);
for (size_t i = 0; i < L; ++i)
{
auto& sel = signature.elements[i];
hs_calculator.add_point(sel.Z0);
hs_calculator.add_point(sel.T0);
hs_calculator.add_point(sel.Z);
}
e = hs_calculator.calc_hash();
scalar_t c0 = e;
return false;
// check t0 * Z0 + c0 * Z == T0
for (size_t i = 0; i < L; ++i)
{
auto& sel = signature.elements[i];
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sel.t0 * sel.Z0 + c0 * sel.Z == sel.T0, 7);
}
// challenges c11, c13
std::vector<scalar_t> c1_array; // counting from 0, so c11 is c1_array[0], will have n elements
std::vector<scalar_t> c3_array; // the same, will have n - 1 elements
hs_calculator.add_scalar(e);
for (size_t i = 0; i < L; ++i)
{
auto& sel = signature.elements[i];
hs_calculator.add_scalar(sel.t0);
hs_calculator.add_point(sel.H_array[0]);
}
e = hs_calculator.calc_hash();
c1_array.emplace_back(e);
c3_array.emplace_back(hash_helper_t::hs(e));
// ci1, ci3 for i in [2; n] -- corresponds c1_array for i in [1; n - 1], c3_array for i in [1; n - 2]
for (size_t i = 1; i < n; ++i)
{
hs_calculator.add_scalar(e);
for (size_t j = 0; j < L; ++j)
{
auto& sel = signature.elements[j];
hs_calculator.add_scalar(sel.r_array[i - 1]);
hs_calculator.add_point(sel.H_array[i]);
}
e = hs_calculator.calc_hash();
c1_array.emplace_back(e);
if (i != n - 1)
c3_array.emplace_back(hash_helper_t::hs(e));
}
// challenge c
hs_calculator.add_scalar(e);
for (size_t i = 0; i < L; ++i)
{
auto& sel = signature.elements[i];
hs_calculator.add_scalar(sel.r_array[n - 1]);
hs_calculator.add_point(sel.T);
}
scalar_t c = hs_calculator.calc_hash();
// Rsum
point_t R = c_point_G;
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ml2s_rsum(n, X_array, c1_array, c3_array, R), 8);
// final checks
for (size_t i = 0; i < L; ++i)
{
auto& sel = signature.elements[i];
point_t S = sel.Z;
for (size_t j = 0; j < n; ++j)
{
S = S + sel.r_array[j] * sel.H_array[j];
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(!S.is_zero(), 9);
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sel.r_array[j] != 0, 10);
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(!sel.H_array[j].is_zero(), 11);
}
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sel.t * S + c * R == sel.T, 12);
}
return true;
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
}