mirror of
https://github.com/monero-project/monero.git
synced 2025-03-30 17:18:01 -04:00
move X25519 tests to their own file
This commit is contained in:
parent
5f5981c4df
commit
ee3a8697d6
@ -105,6 +105,7 @@ set(unit_tests_sources
|
||||
is_hdd.cpp
|
||||
aligned.cpp
|
||||
rpc_version_str.cpp
|
||||
x25519.cpp
|
||||
zmq_rpc.cpp)
|
||||
|
||||
set(unit_tests_headers
|
||||
|
@ -39,10 +39,8 @@ extern "C"
|
||||
#include "crypto/generators.h"
|
||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||
#include "cryptonote_basic/merge_mining.h"
|
||||
#include "mx25519.h"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "ringct/rctTypes.h"
|
||||
#include "string_tools.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -58,6 +56,7 @@ namespace
|
||||
"6c7251d54154cfa92c173a0dd39c1f948b655970153799af2aeadc9ff1add0ea";
|
||||
|
||||
template<typename T> void *addressof(T &t) { return &t; }
|
||||
template<> void *addressof(crypto::secret_key &k) { return addressof(unwrap(unwrap(k))); }
|
||||
|
||||
template<typename T>
|
||||
bool is_formatted()
|
||||
@ -73,62 +72,6 @@ namespace
|
||||
out << "BEGIN" << value << "END";
|
||||
return out.str() == "BEGIN<" + std::string{expected, sizeof(T) * 2} + ">END";
|
||||
}
|
||||
|
||||
std::vector<const mx25519_impl*> get_available_mx25519_impls()
|
||||
{
|
||||
static constexpr const mx25519_type ALL_IMPL_TYPES[4] = {MX25519_TYPE_PORTABLE,
|
||||
MX25519_TYPE_ARM64,
|
||||
MX25519_TYPE_AMD64,
|
||||
MX25519_TYPE_AMD64X};
|
||||
static constexpr const size_t NUM_IMPLS = sizeof(ALL_IMPL_TYPES) / sizeof(ALL_IMPL_TYPES[0]);
|
||||
|
||||
std::vector<const mx25519_impl*> available_impls;
|
||||
available_impls.reserve(NUM_IMPLS);
|
||||
for (int i = 0; i < NUM_IMPLS; ++i)
|
||||
{
|
||||
const mx25519_type impl_type = ALL_IMPL_TYPES[i];
|
||||
const mx25519_impl * const impl = mx25519_select_impl(impl_type);
|
||||
if (nullptr == impl)
|
||||
continue;
|
||||
available_impls.push_back(impl);
|
||||
}
|
||||
|
||||
return available_impls;
|
||||
}
|
||||
|
||||
std::string get_name_of_mx25519_impl(const mx25519_impl* impl)
|
||||
{
|
||||
# define get_name_of_mx25519_impl_CASE(x) case x: return #x;
|
||||
CHECK_AND_ASSERT_THROW_MES(impl != nullptr, "null impl");
|
||||
const mx25519_type impl_type = mx25519_impl_type(impl);
|
||||
switch (impl_type)
|
||||
{
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_PORTABLE)
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_ARM64)
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_AMD64)
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_AMD64X)
|
||||
default:
|
||||
throw std::runtime_error("get name of mx25519 impl: unrecognized impl type");
|
||||
}
|
||||
# undef get_name_of_mx25519_impl_CASE
|
||||
}
|
||||
|
||||
void dump_mx25519_impls(const std::vector<const mx25519_impl*> &impls)
|
||||
{
|
||||
std::cout << "Testing " << impls.size() << " mx25519 implementations:" << std::endl;
|
||||
for (const mx25519_impl *impl : impls)
|
||||
std::cout << " - " << get_name_of_mx25519_impl(impl) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool operator==(const mx25519_pubkey &a, const mx25519_pubkey &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(mx25519_pubkey)) == 0;
|
||||
}
|
||||
|
||||
static inline bool operator!=(const mx25519_pubkey &a, const mx25519_pubkey &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
TEST(Crypto, Ostream)
|
||||
@ -402,225 +345,3 @@ TEST(Crypto, generator_consistency)
|
||||
// ringct/rctTypes.h
|
||||
ASSERT_TRUE(memcmp(H.data, rct::H.bytes, 32) == 0);
|
||||
}
|
||||
|
||||
TEST(Crypto, x25519_impl_scmul_key_convergence)
|
||||
{
|
||||
std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
if (available_impls.size() < 2)
|
||||
return;
|
||||
|
||||
dump_mx25519_impls(available_impls);
|
||||
|
||||
mx25519_pubkey P_fixed;
|
||||
epee::string_tools::hex_to_pod("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", P_fixed);
|
||||
|
||||
mx25519_pubkey P_random;
|
||||
rct::key tmp = rct::pkGen();
|
||||
edwards_bytes_to_x25519_vartime(P_random.data, tmp.bytes);
|
||||
|
||||
tmp = rct::skGen();
|
||||
mx25519_privkey a;
|
||||
memcpy(&a, &tmp, sizeof(a));
|
||||
|
||||
mx25519_pubkey res_fixed;
|
||||
mx25519_pubkey res_random;
|
||||
|
||||
bool first = true;
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
mx25519_pubkey tmp_mx;
|
||||
mx25519_scmul_key(impl, &tmp_mx, &a, &P_fixed);
|
||||
if (!first)
|
||||
{
|
||||
EXPECT_EQ(res_fixed, tmp_mx);
|
||||
}
|
||||
|
||||
memcpy(&res_fixed, &tmp_mx, 32);
|
||||
|
||||
mx25519_scmul_key(impl, &tmp_mx, &a, &P_random);
|
||||
if (!first)
|
||||
{
|
||||
EXPECT_EQ(res_random, tmp_mx);
|
||||
}
|
||||
|
||||
memcpy(&res_random, &tmp_mx, 32);
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, x25519_secret_key_1_scmul_base)
|
||||
{
|
||||
const crypto::secret_key one({crypto::ec_scalar{.data = {1}}});
|
||||
const mx25519_pubkey B{.data={9}};
|
||||
|
||||
const std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
mx25519_pubkey B1;
|
||||
mx25519_scmul_base(impl, &B1, reinterpret_cast<const mx25519_privkey*>(&one));
|
||||
|
||||
EXPECT_EQ(B, B1);
|
||||
if (B1 != B)
|
||||
{
|
||||
std::cout << "Failure occurred with " << get_name_of_mx25519_impl(impl) << " impl" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, x25519_secret_key_2_scmul_base)
|
||||
{
|
||||
const crypto::secret_key two({crypto::ec_scalar{.data = {2}}});
|
||||
const rct::key G_doubled = rct::addKeys(rct::G, rct::G);
|
||||
mx25519_pubkey B_doubled;
|
||||
edwards_bytes_to_x25519_vartime(B_doubled.data, G_doubled.bytes);
|
||||
|
||||
const std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
mx25519_pubkey B2;
|
||||
mx25519_scmul_base(impl, &B2, reinterpret_cast<const mx25519_privkey*>(&two));
|
||||
|
||||
EXPECT_EQ(B_doubled, B2);
|
||||
if (B2 != B_doubled)
|
||||
{
|
||||
std::cout << "Failure occurred with " << get_name_of_mx25519_impl(impl) << " impl" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, x25519_secret_key_4_scmul_base)
|
||||
{
|
||||
const crypto::secret_key four({crypto::ec_scalar{.data = {4}}});
|
||||
const rct::key G_quad = rct::scalarmultBase({.bytes = {4}});
|
||||
mx25519_pubkey B_quad;
|
||||
edwards_bytes_to_x25519_vartime(B_quad.data, G_quad.bytes);
|
||||
|
||||
const std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
mx25519_pubkey B4;
|
||||
mx25519_scmul_base(impl, &B4, reinterpret_cast<const mx25519_privkey*>(&four));
|
||||
|
||||
EXPECT_EQ(B_quad, B4);
|
||||
if (B4 != B_quad)
|
||||
{
|
||||
std::cout << "Failure occurred with " << get_name_of_mx25519_impl(impl) << " impl" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, x25519_secret_key_8_scmul_base)
|
||||
{
|
||||
const crypto::secret_key eight({crypto::ec_scalar{.data = {8}}});
|
||||
const rct::key G_oct = rct::scalarmultBase({.bytes = {8}});
|
||||
mx25519_pubkey B_oct;
|
||||
edwards_bytes_to_x25519_vartime(B_oct.data, G_oct.bytes);
|
||||
|
||||
const std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
mx25519_pubkey B8;
|
||||
mx25519_scmul_base(impl, &B8, reinterpret_cast<const mx25519_privkey*>(&eight));
|
||||
|
||||
EXPECT_EQ(B_oct, B8);
|
||||
if (B8 != B_oct)
|
||||
{
|
||||
std::cout << "Failure occurred with " << get_name_of_mx25519_impl(impl) << " impl" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, ConvertPointE_Base)
|
||||
{
|
||||
const crypto::public_key G = crypto::get_G();
|
||||
const mx25519_pubkey B_expected = {{9}};
|
||||
|
||||
mx25519_pubkey B_actual;
|
||||
edwards_bytes_to_x25519_vartime(B_actual.data, to_bytes(G));
|
||||
|
||||
EXPECT_EQ(B_expected, B_actual);
|
||||
}
|
||||
|
||||
TEST(Crypto, ConvertPointE_PreserveScalarMultBase)
|
||||
{
|
||||
const std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
// *clamped* private key a
|
||||
const crypto::secret_key a = rct::rct2sk(rct::skGen());
|
||||
rct::key a_key;
|
||||
memcpy(&a_key, &a, sizeof(rct::key));
|
||||
|
||||
// P_ed = a G
|
||||
const rct::key P_edward = rct::scalarmultBase(a_key);
|
||||
|
||||
// P_mont = a B
|
||||
mx25519_pubkey P_mont;
|
||||
mx25519_scmul_base(impl, &P_mont, reinterpret_cast<const mx25519_privkey*>(&a));
|
||||
|
||||
// P_mont' = ConvertPointE(P_ed)
|
||||
mx25519_pubkey P_mont_converted;
|
||||
edwards_bytes_to_x25519_vartime(P_mont_converted.data, P_edward.bytes);
|
||||
|
||||
// P_mont' ?= P_mont
|
||||
EXPECT_EQ(P_mont_converted, P_mont);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, ConvertPointE_PreserveScalarMultBase_gep3)
|
||||
{
|
||||
// compared to ConvertPointE_PreserveScalarMultBase, this test will use Z != 1 (probably)
|
||||
|
||||
const std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
const crypto::secret_key a = rct::rct2sk(rct::skGen());
|
||||
rct::key a_key;
|
||||
memcpy(&a_key, &a, sizeof(rct::key));
|
||||
|
||||
// P_ed = a G
|
||||
ge_p3 P_p3;
|
||||
ge_scalarmult_base(&P_p3, to_bytes(a));
|
||||
|
||||
// check that Z != 1, otherwise this test is a dup of ConvertPointE_PreserveScalarMultBase
|
||||
rct::key Z_bytes;
|
||||
fe_tobytes(Z_bytes.bytes, P_p3.Z);
|
||||
ASSERT_NE(Z_bytes, rct::I); // check Z != 1
|
||||
|
||||
// P_mont = a B
|
||||
mx25519_pubkey P_mont;
|
||||
mx25519_scmul_base(impl, &P_mont, reinterpret_cast<const mx25519_privkey*>(&a));
|
||||
|
||||
// P_mont' = ConvertPointE(P_ed)
|
||||
mx25519_pubkey P_mont_converted;
|
||||
ge_p3_to_x25519(P_mont_converted.data, &P_p3);
|
||||
|
||||
// P_mont' ?= P_mont
|
||||
EXPECT_EQ(P_mont_converted, P_mont);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, ConvertPointE_EraseSign)
|
||||
{
|
||||
// generate a random point P and test that ConvertPointE(P) == ConvertPointE(-P)
|
||||
|
||||
const rct::key P = rct::pkGen();
|
||||
rct::key negP;
|
||||
rct::subKeys(negP, rct::I, P);
|
||||
|
||||
mx25519_pubkey P_mont;
|
||||
edwards_bytes_to_x25519_vartime(P_mont.data, P.bytes);
|
||||
|
||||
mx25519_pubkey negP_mont;
|
||||
edwards_bytes_to_x25519_vartime(negP_mont.data, negP.bytes);
|
||||
|
||||
EXPECT_EQ(P_mont, negP_mont);
|
||||
}
|
||||
|
205
tests/unit_tests/x25519.cpp
Normal file
205
tests/unit_tests/x25519.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright (c) 2017-2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cstring>
|
||||
#include <gtest/gtest.h>
|
||||
#include <vector>
|
||||
|
||||
#include "common/container_helpers.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "crypto/crypto-ops.h"
|
||||
}
|
||||
#include "crypto/generators.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "mx25519.h"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "string_tools.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
static std::vector<const mx25519_impl*> get_available_mx25519_impls()
|
||||
{
|
||||
static constexpr const mx25519_type ALL_IMPL_TYPES[4] = {MX25519_TYPE_PORTABLE,
|
||||
MX25519_TYPE_ARM64,
|
||||
MX25519_TYPE_AMD64,
|
||||
MX25519_TYPE_AMD64X};
|
||||
static constexpr const size_t NUM_IMPLS = sizeof(ALL_IMPL_TYPES) / sizeof(ALL_IMPL_TYPES[0]);
|
||||
|
||||
std::vector<const mx25519_impl*> available_impls;
|
||||
available_impls.reserve(NUM_IMPLS);
|
||||
for (int i = 0; i < NUM_IMPLS; ++i)
|
||||
{
|
||||
const mx25519_type impl_type = ALL_IMPL_TYPES[i];
|
||||
const mx25519_impl * const impl = mx25519_select_impl(impl_type);
|
||||
if (nullptr == impl)
|
||||
continue;
|
||||
available_impls.push_back(impl);
|
||||
}
|
||||
|
||||
return available_impls;
|
||||
}
|
||||
|
||||
static std::string get_name_of_mx25519_impl(const mx25519_impl* impl)
|
||||
{
|
||||
# define get_name_of_mx25519_impl_CASE(x) case x: return #x;
|
||||
CHECK_AND_ASSERT_THROW_MES(impl != nullptr, "null impl");
|
||||
const mx25519_type impl_type = mx25519_impl_type(impl);
|
||||
switch (impl_type)
|
||||
{
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_PORTABLE)
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_ARM64)
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_AMD64)
|
||||
get_name_of_mx25519_impl_CASE(MX25519_TYPE_AMD64X)
|
||||
default:
|
||||
throw std::runtime_error("get name of mx25519 impl: unrecognized impl type");
|
||||
}
|
||||
# undef get_name_of_mx25519_impl_CASE
|
||||
}
|
||||
|
||||
void dump_mx25519_impls(const std::vector<const mx25519_impl*> &impls)
|
||||
{
|
||||
std::cout << "Testing " << impls.size() << " mx25519 implementations:" << std::endl;
|
||||
for (const mx25519_impl *impl : impls)
|
||||
std::cout << " - " << get_name_of_mx25519_impl(impl) << std::endl;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T hex2pod(boost::string_ref s)
|
||||
{
|
||||
T v;
|
||||
if (!epee::string_tools::hex_to_pod(s, v))
|
||||
throw std::runtime_error("hex2pod conversion failed");
|
||||
return v;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
static inline bool operator==(const mx25519_pubkey &a, const mx25519_pubkey &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(mx25519_pubkey)) == 0;
|
||||
}
|
||||
|
||||
static inline bool operator!=(const mx25519_pubkey &a, const mx25519_pubkey &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
TEST(x25519, scmul_key_convergence)
|
||||
{
|
||||
std::vector<const mx25519_impl*> available_impls = get_available_mx25519_impls();
|
||||
|
||||
ASSERT_GT(available_impls.size(), 0);
|
||||
|
||||
dump_mx25519_impls(available_impls);
|
||||
|
||||
std::vector<mx25519_privkey> scalars;
|
||||
for (int i = 0; i <= 254; ++i)
|
||||
{
|
||||
for (unsigned char j = 0; j < 8; ++j)
|
||||
{
|
||||
// add 2^i + j (sometimes with duplicates, which is okay)
|
||||
mx25519_privkey &s = tools::add_element(scalars);
|
||||
memset(s.data, 0, sizeof(mx25519_privkey));
|
||||
const int msb_byte_index = i >> 3;
|
||||
const int msb_bit_index = i & 7;
|
||||
s.data[msb_byte_index] = 1 << msb_bit_index;
|
||||
s.data[0] = j;
|
||||
}
|
||||
}
|
||||
// add -1
|
||||
scalars.push_back(hex2pod<mx25519_privkey>("ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"));
|
||||
// add random
|
||||
const rct::key a = rct::skGen();
|
||||
memcpy(tools::add_element(scalars).data, &a, sizeof(mx25519_privkey));
|
||||
|
||||
std::vector<std::pair<rct::key, mx25519_pubkey>> points;
|
||||
// add base point
|
||||
points.push_back({rct::G, mx25519_pubkey{.data={9}}});
|
||||
// add RFC 7784 test point
|
||||
points.push_back({
|
||||
hex2pod<rct::key>("8120f299c37ae1ca64a179f638a6c6fafde968f1c33705e28c413c7579d9884f"),
|
||||
hex2pod<mx25519_pubkey>("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a")
|
||||
});
|
||||
// add random point
|
||||
const rct::key P_random = rct::pkGen();
|
||||
mx25519_pubkey P_random_x;
|
||||
edwards_bytes_to_x25519_vartime(P_random_x.data, P_random.bytes);
|
||||
points.push_back({P_random, P_random_x});
|
||||
|
||||
for (const mx25519_privkey &scalar : scalars)
|
||||
{
|
||||
for (const auto &point : points)
|
||||
{
|
||||
// D1 = ConvertPointE(a * P_base)
|
||||
ge_p3 P_ed;
|
||||
ASSERT_EQ(0, ge_frombytes_vartime(&P_ed, point.first.bytes));
|
||||
ge_p3 res_p3;
|
||||
ge_scalarmult_p3(&res_p3, scalar.data, &P_ed);
|
||||
mx25519_pubkey res;
|
||||
ge_p3_to_x25519(res.data, &res_p3);
|
||||
|
||||
for (const mx25519_impl *impl : available_impls)
|
||||
{
|
||||
// D2 = a * D_base
|
||||
mx25519_pubkey res_mx;
|
||||
mx25519_scmul_key(impl, &res_mx, &scalar, &point.second);
|
||||
|
||||
// D1 ?= D2
|
||||
EXPECT_EQ(res, res_mx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(x25519, ConvertPointE_Base)
|
||||
{
|
||||
const crypto::public_key G = crypto::get_G();
|
||||
const mx25519_pubkey B_expected = {{9}};
|
||||
|
||||
mx25519_pubkey B_actual;
|
||||
edwards_bytes_to_x25519_vartime(B_actual.data, to_bytes(G));
|
||||
|
||||
EXPECT_EQ(B_expected, B_actual);
|
||||
}
|
||||
|
||||
TEST(x25519, ConvertPointE_EraseSign)
|
||||
{
|
||||
// generate a random point P and test that ConvertPointE(P) == ConvertPointE(-P)
|
||||
|
||||
const rct::key P = rct::pkGen();
|
||||
rct::key negP;
|
||||
rct::subKeys(negP, rct::I, P);
|
||||
|
||||
mx25519_pubkey P_mont;
|
||||
edwards_bytes_to_x25519_vartime(P_mont.data, P.bytes);
|
||||
|
||||
mx25519_pubkey negP_mont;
|
||||
edwards_bytes_to_x25519_vartime(negP_mont.data, negP.bytes);
|
||||
|
||||
EXPECT_EQ(P_mont, negP_mont);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user