remove x25519 wrapper header

This commit is contained in:
jeffro256 2025-01-09 13:15:17 -06:00
parent f85d3cb5c2
commit 5f5981c4df
No known key found for this signature in database
GPG Key ID: 6F79797A6E392442
22 changed files with 206 additions and 378 deletions

View File

@ -48,6 +48,7 @@ target_link_libraries(carrot_core
PUBLIC PUBLIC
cncrypto cncrypto
epee epee
mx25519_static
ringct ringct
seraphis_crypto seraphis_crypto
PRIVATE PRIVATE

View File

@ -104,7 +104,7 @@ bool verify_carrot_janus_protection(const input_context_t &input_context,
const view_incoming_key_device &k_view_dev, const view_incoming_key_device &k_view_dev,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
const crypto::public_key &nominal_address_spend_pubkey, const crypto::public_key &nominal_address_spend_pubkey,
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const janus_anchor_t &nominal_anchor, const janus_anchor_t &nominal_anchor,
payment_id_t &nominal_payment_id_inout) payment_id_t &nominal_payment_id_inout)
{ {
@ -159,7 +159,7 @@ bool verify_carrot_janus_protection(const input_context_t &input_context,
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
bool try_scan_carrot_coinbase_enote(const CarrotCoinbaseEnoteV1 &enote, bool try_scan_carrot_coinbase_enote(const CarrotCoinbaseEnoteV1 &enote,
const crypto::x25519_pubkey &s_sender_receiver_unctx, const mx25519_pubkey &s_sender_receiver_unctx,
const view_incoming_key_device &k_view_dev, const view_incoming_key_device &k_view_dev,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
crypto::secret_key &sender_extension_g_out, crypto::secret_key &sender_extension_g_out,
@ -228,7 +228,7 @@ bool try_scan_carrot_coinbase_enote(const CarrotCoinbaseEnoteV1 &enote,
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
bool try_scan_carrot_enote_external(const CarrotEnoteV1 &enote, bool try_scan_carrot_enote_external(const CarrotEnoteV1 &enote,
const std::optional<encrypted_payment_id_t> encrypted_payment_id, const std::optional<encrypted_payment_id_t> encrypted_payment_id,
const crypto::x25519_pubkey &s_sender_receiver_unctx, const mx25519_pubkey &s_sender_receiver_unctx,
const view_incoming_key_device &k_view_dev, const view_incoming_key_device &k_view_dev,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
crypto::secret_key &sender_extension_g_out, crypto::secret_key &sender_extension_g_out,

View File

@ -49,12 +49,12 @@ bool verify_carrot_janus_protection(const input_context_t &input_context,
const view_incoming_key_device &k_view_dev, const view_incoming_key_device &k_view_dev,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
const crypto::public_key &nominal_address_spend_pubkey, const crypto::public_key &nominal_address_spend_pubkey,
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const janus_anchor_t &nominal_anchor, const janus_anchor_t &nominal_anchor,
payment_id_t &nominal_payment_id_inout); payment_id_t &nominal_payment_id_inout);
bool try_scan_carrot_coinbase_enote(const CarrotCoinbaseEnoteV1 &enote, bool try_scan_carrot_coinbase_enote(const CarrotCoinbaseEnoteV1 &enote,
const crypto::x25519_pubkey &s_sender_receiver_unctx, const mx25519_pubkey &s_sender_receiver_unctx,
const view_incoming_key_device &k_view_dev, const view_incoming_key_device &k_view_dev,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
crypto::secret_key &sender_extension_g_out, crypto::secret_key &sender_extension_g_out,
@ -63,7 +63,7 @@ bool try_scan_carrot_coinbase_enote(const CarrotCoinbaseEnoteV1 &enote,
bool try_scan_carrot_enote_external(const CarrotEnoteV1 &enote, bool try_scan_carrot_enote_external(const CarrotEnoteV1 &enote,
const std::optional<encrypted_payment_id_t> encrypted_payment_id, const std::optional<encrypted_payment_id_t> encrypted_payment_id,
const crypto::x25519_pubkey &s_sender_receiver_unctx, const mx25519_pubkey &s_sender_receiver_unctx,
const view_incoming_key_device &k_view_dev, const view_incoming_key_device &k_view_dev,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
crypto::secret_key &sender_extension_g_out, crypto::secret_key &sender_extension_g_out,

View File

@ -31,8 +31,8 @@
#pragma once #pragma once
//local headers //local headers
#include "crypto/x25519.h"
#include "core_types.h" #include "core_types.h"
#include "mx25519.h"
#include "ringct/rctTypes.h" #include "ringct/rctTypes.h"
//third party headers //third party headers
@ -66,7 +66,7 @@ struct CarrotEnoteV1 final
/// view_tag /// view_tag
view_tag_t view_tag; view_tag_t view_tag;
/// D_e /// D_e
crypto::x25519_pubkey enote_ephemeral_pubkey; mx25519_pubkey enote_ephemeral_pubkey;
/// L_0 /// L_0
crypto::key_image tx_first_key_image; crypto::key_image tx_first_key_image;
}; };
@ -89,7 +89,7 @@ struct CarrotCoinbaseEnoteV1 final
/// view_tag /// view_tag
view_tag_t view_tag; view_tag_t view_tag;
/// D_e /// D_e
crypto::x25519_pubkey enote_ephemeral_pubkey; mx25519_pubkey enote_ephemeral_pubkey;
/// block_index /// block_index
std::uint64_t block_index; std::uint64_t block_index;
}; };

View File

@ -31,6 +31,10 @@
//local headers //local headers
#include "crypto/crypto.h" #include "crypto/crypto.h"
extern "C"
{
#include "crypto/crypto-ops.h"
}
//third party headers //third party headers
#include <cstring> #include <cstring>
@ -118,4 +122,16 @@ input_context_t gen_input_context()
return crypto::rand<input_context_t>(); return crypto::rand<input_context_t>();
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
mx25519_pubkey gen_x25519_pubkey()
{
unsigned char sc64[64];
crypto::rand(sizeof(sc64), sc64);
sc_reduce(sc64);
ge_p3 P;
ge_scalarmult_base(&P, sc64);
mx25519_pubkey P_x25519;
ge_p3_to_x25519(P_x25519.data, &P);
return P_x25519;
}
//-------------------------------------------------------------------------------------------------------------------
} //namespace carrot } //namespace carrot

View File

@ -31,6 +31,7 @@
#pragma once #pragma once
//local headers //local headers
#include "mx25519.h"
//third party headers //third party headers
@ -126,5 +127,7 @@ payment_id_t gen_payment_id();
view_tag_t gen_view_tag(); view_tag_t gen_view_tag();
/// generate a random input context /// generate a random input context
input_context_t gen_input_context(); input_context_t gen_input_context();
/// generate a random X25519 pubkey (unclamped)
mx25519_pubkey gen_x25519_pubkey();
} //namespace carrot } //namespace carrot

View File

@ -33,7 +33,7 @@
//local headers //local headers
#include "core_types.h" #include "core_types.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/x25519.h" #include "mx25519.h"
//third party headers //third party headers
@ -118,8 +118,8 @@ struct view_incoming_key_device
* outparam: kvD = k_v D * outparam: kvD = k_v D
* return: true on success, false on failure (e.g. unable to decompress point) * return: true on success, false on failure (e.g. unable to decompress point)
*/ */
virtual bool view_key_scalar_mult_x25519(const crypto::x25519_pubkey &D, virtual bool view_key_scalar_mult_x25519(const mx25519_pubkey &D,
crypto::x25519_pubkey &kvD) const = 0; mx25519_pubkey &kvD) const = 0;
/** /**
* brief: make_janus_anchor_special - make a janus anchor for "special" enotes * brief: make_janus_anchor_special - make a janus anchor for "special" enotes
@ -128,7 +128,7 @@ struct view_incoming_key_device
* param: account_spend_pubkey - K_s * param: account_spend_pubkey - K_s
* outparam: anchor_special_out - anchor_sp = anchor_sp = H_16(D_e, input_context, Ko, k_v, K_s) * outparam: anchor_special_out - anchor_sp = anchor_sp = H_16(D_e, input_context, Ko, k_v, K_s)
*/ */
virtual void make_janus_anchor_special(const crypto::x25519_pubkey &enote_ephemeral_pubkey, virtual void make_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
const crypto::public_key &onetime_address, const crypto::public_key &onetime_address,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
@ -155,7 +155,7 @@ struct view_balance_secret_device
* param: input_context - input_context * param: input_context - input_context
* outparam: s_sender_receiver_out - s_sr = s^ctx_sr = H_32(s_sr, D_e, input_context) * outparam: s_sender_receiver_out - s_sr = s^ctx_sr = H_32(s_sr, D_e, input_context)
*/ */
virtual void make_internal_sender_receiver_secret(const crypto::x25519_pubkey &enote_ephemeral_pubkey, virtual void make_internal_sender_receiver_secret(const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
crypto::hash &s_sender_receiver_out) const = 0; crypto::hash &s_sender_receiver_out) const = 0;

View File

@ -48,14 +48,14 @@ bool view_incoming_key_ram_borrowed_device::view_key_scalar_mult_ed25519(const c
return true; return true;
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
bool view_incoming_key_ram_borrowed_device::view_key_scalar_mult_x25519(const crypto::x25519_pubkey &D, bool view_incoming_key_ram_borrowed_device::view_key_scalar_mult_x25519(const mx25519_pubkey &D,
crypto::x25519_pubkey &kvD) const mx25519_pubkey &kvD) const
{ {
return make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming, D, kvD); return make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming, D, kvD);
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
void view_incoming_key_ram_borrowed_device::make_janus_anchor_special( void view_incoming_key_ram_borrowed_device::make_janus_anchor_special(
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
const crypto::public_key &onetime_address, const crypto::public_key &onetime_address,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
@ -77,7 +77,7 @@ void view_balance_secret_ram_borrowed_device::make_internal_view_tag(const input
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
void view_balance_secret_ram_borrowed_device::make_internal_sender_receiver_secret( void view_balance_secret_ram_borrowed_device::make_internal_sender_receiver_secret(
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
crypto::hash &s_sender_receiver_out) const crypto::hash &s_sender_receiver_out) const
{ {

View File

@ -52,10 +52,10 @@ public:
bool view_key_scalar_mult_ed25519(const crypto::public_key &P, bool view_key_scalar_mult_ed25519(const crypto::public_key &P,
crypto::public_key &kvP) const override; crypto::public_key &kvP) const override;
bool view_key_scalar_mult_x25519(const crypto::x25519_pubkey &D, bool view_key_scalar_mult_x25519(const mx25519_pubkey &D,
crypto::x25519_pubkey &kvD) const override; mx25519_pubkey &kvD) const override;
void make_janus_anchor_special(const crypto::x25519_pubkey &enote_ephemeral_pubkey, void make_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
const crypto::public_key &onetime_address, const crypto::public_key &onetime_address,
const crypto::public_key &account_spend_pubkey, const crypto::public_key &account_spend_pubkey,
@ -75,7 +75,7 @@ public:
const crypto::public_key &onetime_address, const crypto::public_key &onetime_address,
view_tag_t &view_tag_out) const override; view_tag_t &view_tag_out) const override;
void make_internal_sender_receiver_secret(const crypto::x25519_pubkey &enote_ephemeral_pubkey, void make_internal_sender_receiver_secret(const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
crypto::hash &s_sender_receiver_out) const override; crypto::hash &s_sender_receiver_out) const override;

View File

@ -46,6 +46,7 @@ extern "C"
//third party headers //third party headers
//standard headers //standard headers
#include <mutex>
#undef MONERO_DEFAULT_LOG_CATEGORY #undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "carrot" #define MONERO_DEFAULT_LOG_CATEGORY "carrot"
@ -54,6 +55,17 @@ namespace carrot
{ {
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
static const mx25519_impl* get_mx25519_impl()
{
static std::once_flag of;
static const mx25519_impl *impl;
std::call_once(of, [&](){ impl = mx25519_select_impl(MX25519_TYPE_AUTO); });
if (impl == nullptr)
throw std::runtime_error("failed to obtain a mx25519 implementation");
return impl;
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
static encrypted_amount_t enc_amount(const rct::xmr_amount amount, const encrypted_amount_t &mask) static encrypted_amount_t enc_amount(const rct::xmr_amount amount, const encrypted_amount_t &mask)
{ {
static_assert(sizeof(rct::xmr_amount) == sizeof(encrypted_amount_t), ""); static_assert(sizeof(rct::xmr_amount) == sizeof(encrypted_amount_t), "");
@ -91,19 +103,17 @@ void make_carrot_enote_ephemeral_privkey(const janus_anchor_t &anchor_norm,
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &enote_ephemeral_privkey, void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &enote_ephemeral_privkey,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out) mx25519_pubkey &enote_ephemeral_pubkey_out)
{ {
// K_e = d_e G // D_e = d_e G
ge_p3 D_e_in_ed25519; mx25519_scmul_base(get_mx25519_impl(),
ge_scalarmult_base(&D_e_in_ed25519, to_bytes(enote_ephemeral_privkey)); &enote_ephemeral_pubkey_out,
reinterpret_cast<const mx25519_privkey*>(&enote_ephemeral_privkey));
// D_e = ConvertPointE(K_e)
ge_p3_to_x25519(enote_ephemeral_pubkey_out.data, &D_e_in_ed25519);
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &enote_ephemeral_privkey, void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &enote_ephemeral_privkey,
const crypto::public_key &address_spend_pubkey, const crypto::public_key &address_spend_pubkey,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out) mx25519_pubkey &enote_ephemeral_pubkey_out)
{ {
// deserialize K^j_s // deserialize K^j_s
ge_p3 address_spend_pubkey_p3; ge_p3 address_spend_pubkey_p3;
@ -118,18 +128,21 @@ void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &eno
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
bool make_carrot_uncontextualized_shared_key_receiver(const crypto::secret_key &k_view, bool make_carrot_uncontextualized_shared_key_receiver(const crypto::secret_key &k_view,
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
crypto::x25519_pubkey &s_sender_receiver_unctx_out) mx25519_pubkey &s_sender_receiver_unctx_out)
{ {
// s_sr = k_v D_e // s_sr = k_v D_e
crypto::x25519_scmul_key(k_view, enote_ephemeral_pubkey, s_sender_receiver_unctx_out); mx25519_scmul_key(get_mx25519_impl(),
&s_sender_receiver_unctx_out,
reinterpret_cast<const mx25519_privkey*>(&k_view),
&enote_ephemeral_pubkey);
return true; return true;
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
bool make_carrot_uncontextualized_shared_key_sender(const crypto::secret_key &enote_ephemeral_privkey, bool make_carrot_uncontextualized_shared_key_sender(const crypto::secret_key &enote_ephemeral_privkey,
const crypto::public_key &address_view_pubkey, const crypto::public_key &address_view_pubkey,
crypto::x25519_pubkey &s_sender_receiver_unctx_out) mx25519_pubkey &s_sender_receiver_unctx_out)
{ {
// if K^j_v not in prime order subgroup, then FAIL // if K^j_v not in prime order subgroup, then FAIL
ge_p3 address_view_pubkey_p3; ge_p3 address_view_pubkey_p3;
@ -137,11 +150,14 @@ bool make_carrot_uncontextualized_shared_key_sender(const crypto::secret_key &en
return false; return false;
// D^j_v = ConvertPointE(K^j_v) // D^j_v = ConvertPointE(K^j_v)
crypto::x25519_pubkey address_view_pubkey_x25519; mx25519_pubkey address_view_pubkey_x25519;
ge_p3_to_x25519(address_view_pubkey_x25519.data, &address_view_pubkey_p3); ge_p3_to_x25519(address_view_pubkey_x25519.data, &address_view_pubkey_p3);
// s_sr = d_e D^j_v // s_sr = d_e D^j_v
crypto::x25519_scmul_key(enote_ephemeral_privkey, address_view_pubkey_x25519, s_sender_receiver_unctx_out); mx25519_scmul_key(get_mx25519_impl(),
&s_sender_receiver_unctx_out,
reinterpret_cast<const mx25519_privkey*>(&enote_ephemeral_privkey),
&address_view_pubkey_x25519);
return true; return true;
} }
@ -172,7 +188,7 @@ void make_carrot_input_context(const crypto::key_image &first_rct_key_image, inp
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
void make_carrot_sender_receiver_secret(const unsigned char s_sender_receiver_unctx[32], void make_carrot_sender_receiver_secret(const unsigned char s_sender_receiver_unctx[32],
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
crypto::hash &s_sender_receiver_out) crypto::hash &s_sender_receiver_out)
{ {
@ -347,7 +363,7 @@ payment_id_t decrypt_legacy_payment_id(const encrypted_payment_id_t encrypted_pa
return encrypted_payment_id ^ mask; return encrypted_payment_id ^ mask;
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
void make_carrot_janus_anchor_special(const crypto::x25519_pubkey &enote_ephemeral_pubkey, void make_carrot_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
const crypto::public_key &onetime_address, const crypto::public_key &onetime_address,
const crypto::secret_key &k_view, const crypto::secret_key &k_view,
@ -455,7 +471,7 @@ bool verify_carrot_external_janus_protection(const janus_anchor_t &nominal_ancho
const crypto::public_key &nominal_address_view_pubkey, const crypto::public_key &nominal_address_view_pubkey,
const bool is_subaddress, const bool is_subaddress,
const payment_id_t nominal_payment_id, const payment_id_t nominal_payment_id,
const crypto::x25519_pubkey &enote_ephemeral_pubkey) const mx25519_pubkey &enote_ephemeral_pubkey)
{ {
// d_e' = H_n(anchor_norm, input_context, K^j_s, K^j_v, pid)) // d_e' = H_n(anchor_norm, input_context, K^j_s, K^j_v, pid))
crypto::secret_key nominal_enote_ephemeral_privkey; crypto::secret_key nominal_enote_ephemeral_privkey;
@ -467,7 +483,7 @@ bool verify_carrot_external_janus_protection(const janus_anchor_t &nominal_ancho
nominal_enote_ephemeral_privkey); nominal_enote_ephemeral_privkey);
// recompute D_e' for d_e' and address type // recompute D_e' for d_e' and address type
crypto::x25519_pubkey nominal_enote_ephemeral_pubkey; mx25519_pubkey nominal_enote_ephemeral_pubkey;
if (is_subaddress) if (is_subaddress)
make_carrot_enote_ephemeral_pubkey_subaddress(nominal_enote_ephemeral_privkey, make_carrot_enote_ephemeral_pubkey_subaddress(nominal_enote_ephemeral_privkey,
nominal_address_spend_pubkey, nominal_address_spend_pubkey,
@ -477,7 +493,7 @@ bool verify_carrot_external_janus_protection(const janus_anchor_t &nominal_ancho
nominal_enote_ephemeral_pubkey); nominal_enote_ephemeral_pubkey);
// D_e' ?= D_e // D_e' ?= D_e
return nominal_enote_ephemeral_pubkey == enote_ephemeral_pubkey; return 0 == memcmp(&nominal_enote_ephemeral_pubkey, &enote_ephemeral_pubkey, sizeof(mx25519_pubkey));
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
} //namespace carrot } //namespace carrot

View File

@ -32,8 +32,8 @@
//local headers //local headers
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/x25519.h"
#include "core_types.h" #include "core_types.h"
#include "mx25519.h"
#include "ringct/rctTypes.h" #include "ringct/rctTypes.h"
//third party headers //third party headers
@ -68,7 +68,7 @@ void make_carrot_enote_ephemeral_privkey(const janus_anchor_t &anchor_norm,
* outparam: enote_ephemeral_pubkey_out - D_e * outparam: enote_ephemeral_pubkey_out - D_e
*/ */
void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &enote_ephemeral_privkey, void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &enote_ephemeral_privkey,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out); mx25519_pubkey &enote_ephemeral_pubkey_out);
/** /**
* brief: make_carrot_enote_ephemeral_pubkey_subaddress - make enote ephemeral pubkey D_e for a subaddress * brief: make_carrot_enote_ephemeral_pubkey_subaddress - make enote ephemeral pubkey D_e for a subaddress
* D_e = d_e ConvertPointE(K^j_s) * D_e = d_e ConvertPointE(K^j_s)
@ -78,7 +78,7 @@ void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &eno
*/ */
void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &enote_ephemeral_privkey, void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &enote_ephemeral_privkey,
const crypto::public_key &address_spend_pubkey, const crypto::public_key &address_spend_pubkey,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out); mx25519_pubkey &enote_ephemeral_pubkey_out);
/** /**
* brief: make_carrot_uncontextualized_shared_key_receiver - perform the receiver-side ECDH exchange for Carrot enotes * brief: make_carrot_uncontextualized_shared_key_receiver - perform the receiver-side ECDH exchange for Carrot enotes
* s_sr = k_v D_e * s_sr = k_v D_e
@ -88,8 +88,8 @@ void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &eno
* return: true if successful, false if a failure occurred in point decompression * return: true if successful, false if a failure occurred in point decompression
*/ */
bool make_carrot_uncontextualized_shared_key_receiver(const crypto::secret_key &k_view, bool make_carrot_uncontextualized_shared_key_receiver(const crypto::secret_key &k_view,
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
crypto::x25519_pubkey &s_sender_receiver_unctx_out); mx25519_pubkey &s_sender_receiver_unctx_out);
/** /**
* brief: make_carrot_uncontextualized_shared_key_sender - perform the sender-side ECDH exchange for Carrot enotes * brief: make_carrot_uncontextualized_shared_key_sender - perform the sender-side ECDH exchange for Carrot enotes
* s_sr = d_e ConvertPointE(K^j_v) * s_sr = d_e ConvertPointE(K^j_v)
@ -100,7 +100,7 @@ bool make_carrot_uncontextualized_shared_key_receiver(const crypto::secret_key &
*/ */
bool make_carrot_uncontextualized_shared_key_sender(const crypto::secret_key &enote_ephemeral_privkey, bool make_carrot_uncontextualized_shared_key_sender(const crypto::secret_key &enote_ephemeral_privkey,
const crypto::public_key &address_view_pubkey, const crypto::public_key &address_view_pubkey,
crypto::x25519_pubkey &s_sender_receiver_unctx_out); mx25519_pubkey &s_sender_receiver_unctx_out);
/** /**
* brief: make_carrot_view_tag - used for optimized identification of enotes * brief: make_carrot_view_tag - used for optimized identification of enotes
* vt = H_3(s_sr || input_context || Ko) * vt = H_3(s_sr || input_context || Ko)
@ -137,7 +137,7 @@ void make_carrot_input_context(const crypto::key_image &first_rct_key_image, inp
* - note: this is 'crypto::hash' instead of 'crypto::secret_key' for better performance in multithreaded environments * - note: this is 'crypto::hash' instead of 'crypto::secret_key' for better performance in multithreaded environments
*/ */
void make_carrot_sender_receiver_secret(const unsigned char s_sender_receiver_unctx[32], void make_carrot_sender_receiver_secret(const unsigned char s_sender_receiver_unctx[32],
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
crypto::hash &s_sender_receiver_out); crypto::hash &s_sender_receiver_out);
/** /**
@ -304,7 +304,7 @@ payment_id_t decrypt_legacy_payment_id(const encrypted_payment_id_t encrypted_pa
* param: account_spend_pubkey - K_s * param: account_spend_pubkey - K_s
* outparam: anchor_special_out - anchor_sp * outparam: anchor_special_out - anchor_sp
*/ */
void make_carrot_janus_anchor_special(const crypto::x25519_pubkey &enote_ephemeral_pubkey, void make_carrot_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
const crypto::public_key &onetime_address, const crypto::public_key &onetime_address,
const crypto::secret_key &k_view, const crypto::secret_key &k_view,
@ -388,5 +388,5 @@ bool verify_carrot_external_janus_protection(const janus_anchor_t &nominal_ancho
const crypto::public_key &nominal_address_view_pubkey, const crypto::public_key &nominal_address_view_pubkey,
const bool is_subaddress, const bool is_subaddress,
const payment_id_t nominal_payment_id, const payment_id_t nominal_payment_id,
const crypto::x25519_pubkey &enote_ephemeral_pubkey); const mx25519_pubkey &enote_ephemeral_pubkey);
} //namespace carrot } //namespace carrot

View File

@ -98,7 +98,7 @@ tools::optional_variant<CarrotPaymentProposalV1, CarrotPaymentProposalSelfSendV1
const rct::xmr_amount remaining_change, const rct::xmr_amount remaining_change,
const bool have_payment_type_selfsend, const bool have_payment_type_selfsend,
const crypto::public_key &change_address_spend_pubkey, const crypto::public_key &change_address_spend_pubkey,
const crypto::x25519_pubkey &other_enote_ephemeral_pubkey) const mx25519_pubkey &other_enote_ephemeral_pubkey)
{ {
const std::optional<AdditionalOutputType> additional_output_type = get_additional_output_type( const std::optional<AdditionalOutputType> additional_output_type = get_additional_output_type(
num_outgoing, num_outgoing,
@ -131,7 +131,7 @@ tools::optional_variant<CarrotPaymentProposalV1, CarrotPaymentProposalSelfSendV1
.destination_address_spend_pubkey = change_address_spend_pubkey, .destination_address_spend_pubkey = change_address_spend_pubkey,
.amount = remaining_change, .amount = remaining_change,
.enote_type = CarrotEnoteType::CHANGE, .enote_type = CarrotEnoteType::CHANGE,
.enote_ephemeral_pubkey = crypto::x25519_pubkey_gen() .enote_ephemeral_pubkey = gen_x25519_pubkey()
}; };
case AdditionalOutputType::DUMMY: case AdditionalOutputType::DUMMY:
return CarrotPaymentProposalV1{ return CarrotPaymentProposalV1{
@ -245,7 +245,7 @@ void get_output_enote_proposals(std::vector<CarrotPaymentProposalV1> &&normal_pa
{ {
return memcmp(&a.enote.enote_ephemeral_pubkey, return memcmp(&a.enote.enote_ephemeral_pubkey,
&b.enote.enote_ephemeral_pubkey, &b.enote.enote_ephemeral_pubkey,
sizeof(crypto::x25519_pubkey)) < 0; sizeof(mx25519_pubkey)) < 0;
}; };
std::sort(output_enote_proposals_out.begin(), output_enote_proposals_out.end(), sort_by_ephemeral_pubkey); std::sort(output_enote_proposals_out.begin(), output_enote_proposals_out.end(), sort_by_ephemeral_pubkey);
const bool has_unique_ephemeral_pubkeys = tools::is_sorted_and_unique(output_enote_proposals_out, const bool has_unique_ephemeral_pubkeys = tools::is_sorted_and_unique(output_enote_proposals_out,

View File

@ -85,7 +85,7 @@ tools::optional_variant<CarrotPaymentProposalV1, CarrotPaymentProposalSelfSendV1
const rct::xmr_amount remaining_change, const rct::xmr_amount remaining_change,
const bool have_payment_type_selfsend, const bool have_payment_type_selfsend,
const crypto::public_key &change_address_spend_pubkey, const crypto::public_key &change_address_spend_pubkey,
const crypto::x25519_pubkey &other_enote_ephemeral_pubkey); const mx25519_pubkey &other_enote_ephemeral_pubkey);
/** /**
* brief: get_output_enote_proposals - convert a *finalized* set of payment proposals into output enote proposals * brief: get_output_enote_proposals - convert a *finalized* set of payment proposals into output enote proposals
* param: normal_payment_proposals - * param: normal_payment_proposals -

View File

@ -77,8 +77,8 @@ static crypto::secret_key get_enote_ephemeral_privkey(const CarrotPaymentProposa
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
static void get_normal_proposal_ecdh_parts(const CarrotPaymentProposalV1 &proposal, static void get_normal_proposal_ecdh_parts(const CarrotPaymentProposalV1 &proposal,
const input_context_t &input_context, const input_context_t &input_context,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out, mx25519_pubkey &enote_ephemeral_pubkey_out,
crypto::x25519_pubkey &s_sender_receiver_unctx_out) mx25519_pubkey &s_sender_receiver_unctx_out)
{ {
// 1. d_e = H_n(anchor_norm, input_context, K^j_s, K^j_v, pid)) // 1. d_e = H_n(anchor_norm, input_context, K^j_s, K^j_v, pid))
const crypto::secret_key enote_ephemeral_privkey = get_enote_ephemeral_privkey(proposal, input_context); const crypto::secret_key enote_ephemeral_privkey = get_enote_ephemeral_privkey(proposal, input_context);
@ -98,7 +98,7 @@ static void get_output_proposal_parts(const crypto::hash &s_sender_receiver,
const payment_id_t payment_id, const payment_id_t payment_id,
const rct::xmr_amount amount, const rct::xmr_amount amount,
const CarrotEnoteType enote_type, const CarrotEnoteType enote_type,
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
const bool coinbase_amount_commitment, const bool coinbase_amount_commitment,
crypto::secret_key &amount_blinding_factor_out, crypto::secret_key &amount_blinding_factor_out,
@ -136,12 +136,12 @@ static void get_output_proposal_parts(const crypto::hash &s_sender_receiver,
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
static void get_external_output_proposal_parts(const crypto::x25519_pubkey &s_sender_receiver_unctx, static void get_external_output_proposal_parts(const mx25519_pubkey &s_sender_receiver_unctx,
const crypto::public_key &destination_spend_pubkey, const crypto::public_key &destination_spend_pubkey,
const payment_id_t payment_id, const payment_id_t payment_id,
const rct::xmr_amount amount, const rct::xmr_amount amount,
const CarrotEnoteType enote_type, const CarrotEnoteType enote_type,
const crypto::x25519_pubkey &enote_ephemeral_pubkey, const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context, const input_context_t &input_context,
const bool coinbase_amount_commitment, const bool coinbase_amount_commitment,
crypto::hash &s_sender_receiver_out, crypto::hash &s_sender_receiver_out,
@ -190,8 +190,8 @@ bool operator==(const CarrotPaymentProposalSelfSendV1 &a, const CarrotPaymentPro
return a.destination_address_spend_pubkey == b.destination_address_spend_pubkey && return a.destination_address_spend_pubkey == b.destination_address_spend_pubkey &&
a.amount == b.amount && a.amount == b.amount &&
a.enote_type == b.enote_type && a.enote_type == b.enote_type &&
a.enote_ephemeral_pubkey == b.enote_ephemeral_pubkey && a.internal_message == b.internal_message &&
a.internal_message == b.internal_message; 0 == memcmp(&a.enote_ephemeral_pubkey, &b.enote_ephemeral_pubkey, sizeof(mx25519_pubkey));
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
bool operator<(const RCTOutputEnoteProposal &a, const RCTOutputEnoteProposal &b) bool operator<(const RCTOutputEnoteProposal &a, const RCTOutputEnoteProposal &b)
@ -199,13 +199,13 @@ bool operator<(const RCTOutputEnoteProposal &a, const RCTOutputEnoteProposal &b)
return memcmp(&a.enote.onetime_address, &b.enote.onetime_address, sizeof(crypto::public_key)) < 0; return memcmp(&a.enote.onetime_address, &b.enote.onetime_address, sizeof(crypto::public_key)) < 0;
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
crypto::x25519_pubkey get_enote_ephemeral_pubkey(const CarrotPaymentProposalV1 &proposal, mx25519_pubkey get_enote_ephemeral_pubkey(const CarrotPaymentProposalV1 &proposal,
const input_context_t &input_context) const input_context_t &input_context)
{ {
// d_e = H_n(anchor_norm, input_context, K^j_s, K^j_v, pid)) // d_e = H_n(anchor_norm, input_context, K^j_s, K^j_v, pid))
const crypto::secret_key enote_ephemeral_privkey{get_enote_ephemeral_privkey(proposal, input_context)}; const crypto::secret_key enote_ephemeral_privkey{get_enote_ephemeral_privkey(proposal, input_context)};
crypto::x25519_pubkey enote_ephemeral_pubkey; mx25519_pubkey enote_ephemeral_pubkey;
if (proposal.destination.is_subaddress) if (proposal.destination.is_subaddress)
// D_e = d_e ConvertPointE(K^j_s) // D_e = d_e ConvertPointE(K^j_s)
make_carrot_enote_ephemeral_pubkey_subaddress(enote_ephemeral_privkey, make_carrot_enote_ephemeral_pubkey_subaddress(enote_ephemeral_privkey,
@ -236,7 +236,7 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal,
make_carrot_input_context_coinbase(block_index, input_context); make_carrot_input_context_coinbase(block_index, input_context);
// 3. make D_e and do external ECDH // 3. make D_e and do external ECDH
crypto::x25519_pubkey s_sender_receiver_unctx; auto dhe_wiper = auto_wiper(s_sender_receiver_unctx); mx25519_pubkey s_sender_receiver_unctx; auto dhe_wiper = auto_wiper(s_sender_receiver_unctx);
get_normal_proposal_ecdh_parts(proposal, get_normal_proposal_ecdh_parts(proposal,
input_context, input_context,
output_enote_out.enote_ephemeral_pubkey, output_enote_out.enote_ephemeral_pubkey,
@ -288,7 +288,7 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal,
make_carrot_input_context(tx_first_key_image, input_context); make_carrot_input_context(tx_first_key_image, input_context);
// 3. make D_e and do external ECDH // 3. make D_e and do external ECDH
crypto::x25519_pubkey s_sender_receiver_unctx; auto dhe_wiper = auto_wiper(s_sender_receiver_unctx); mx25519_pubkey s_sender_receiver_unctx; auto dhe_wiper = auto_wiper(s_sender_receiver_unctx);
get_normal_proposal_ecdh_parts(proposal, get_normal_proposal_ecdh_parts(proposal,
input_context, input_context,
output_enote_out.enote.enote_ephemeral_pubkey, output_enote_out.enote.enote_ephemeral_pubkey,
@ -337,7 +337,7 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo
make_carrot_input_context(tx_first_key_image, input_context); make_carrot_input_context(tx_first_key_image, input_context);
// 3. s_sr = k_v D_e // 3. s_sr = k_v D_e
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
CHECK_AND_ASSERT_THROW_MES(k_view_dev.view_key_scalar_mult_x25519(proposal.enote_ephemeral_pubkey, CHECK_AND_ASSERT_THROW_MES(k_view_dev.view_key_scalar_mult_x25519(proposal.enote_ephemeral_pubkey,
s_sender_receiver_unctx), s_sender_receiver_unctx),
"get output proposal special v1: HW device failed to perform ECDH with ephemeral pubkey"); "get output proposal special v1: HW device failed to perform ECDH with ephemeral pubkey");

View File

@ -33,7 +33,6 @@
//local headers //local headers
#include "carrot_enote_types.h" #include "carrot_enote_types.h"
#include "crypto/x25519.h"
#include "destination.h" #include "destination.h"
#include "device.h" #include "device.h"
#include "ringct/rctTypes.h" #include "ringct/rctTypes.h"
@ -77,7 +76,7 @@ struct CarrotPaymentProposalSelfSendV1 final
/// enote_type /// enote_type
CarrotEnoteType enote_type; CarrotEnoteType enote_type;
/// enote ephemeral pubkey: xr G /// enote ephemeral pubkey: xr G
crypto::x25519_pubkey enote_ephemeral_pubkey; mx25519_pubkey enote_ephemeral_pubkey;
/// anchor: arbitrary, pre-encrypted message for _internal_ selfsends /// anchor: arbitrary, pre-encrypted message for _internal_ selfsends
std::optional<janus_anchor_t> internal_message; std::optional<janus_anchor_t> internal_message;
}; };
@ -105,7 +104,7 @@ bool operator<(const RCTOutputEnoteProposal &a, const RCTOutputEnoteProposal &b)
* param: input_context - * param: input_context -
* return: D_e * return: D_e
*/ */
crypto::x25519_pubkey get_enote_ephemeral_pubkey(const CarrotPaymentProposalV1 &proposal, mx25519_pubkey get_enote_ephemeral_pubkey(const CarrotPaymentProposalV1 &proposal,
const input_context_t &input_context); const input_context_t &input_context);
/** /**
* brief: get_coinbase_output_proposal_v1 - convert the carrot proposal to a coinbase output proposal * brief: get_coinbase_output_proposal_v1 - convert the carrot proposal to a coinbase output proposal

View File

@ -50,8 +50,7 @@ set(crypto_sources
slow-hash.c slow-hash.c
rx-slow-hash.c rx-slow-hash.c
CryptonightR_JIT.c CryptonightR_JIT.c
tree-hash.c tree-hash.c)
x25519.cpp)
if(ARCH_ID STREQUAL "i386" OR ARCH_ID STREQUAL "x86_64" OR ARCH_ID STREQUAL "x86-64" OR ARCH_ID STREQUAL "amd64") if(ARCH_ID STREQUAL "i386" OR ARCH_ID STREQUAL "x86_64" OR ARCH_ID STREQUAL "x86-64" OR ARCH_ID STREQUAL "amd64")
list(APPEND crypto_sources CryptonightR_template.S) list(APPEND crypto_sources CryptonightR_template.S)
@ -72,7 +71,6 @@ monero_add_library(cncrypto
target_link_libraries(cncrypto target_link_libraries(cncrypto
PUBLIC PUBLIC
epee epee
mx25519_static
randomx randomx
${Boost_SYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}
${sodium_LIBRARIES} ${sodium_LIBRARIES}

View File

@ -1,116 +0,0 @@
// Copyright (c) 2022, 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.
//paired header
#include "x25519.h"
//local headers
#include "crypto/crypto.h"
extern "C"
{
#include "mx25519.h"
}
//third party headers
//standard headers
#include <vector>
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "crypto"
namespace crypto
{
/// File-scope data
static const ec_scalar X25519_EIGHT{ .data = { 8 } };
//-------------------------------------------------------------------------------------------------------------------
secret_key x25519_secret_key_gen()
{
secret_key privkey;
do
{
crypto::rand(32, to_bytes(privkey));
privkey.data[0] &= 255 - 7;
privkey.data[31] &= 127;
} while (privkey == secret_key{});
return privkey;
}
//-------------------------------------------------------------------------------------------------------------------
x25519_pubkey x25519_pubkey_gen()
{
const secret_key privkey{x25519_secret_key_gen()};
x25519_pubkey pubkey;
x25519_scmul_base(privkey, pubkey);
return pubkey;
}
//-------------------------------------------------------------------------------------------------------------------
bool x25519_scalar_is_canonical(const ec_scalar &test_scalar)
{
//todo: is this constant time?
return (test_scalar.data[0] & 7) == 0 &&
(test_scalar.data[31] & 128) == 0;
}
//-------------------------------------------------------------------------------------------------------------------
void x25519_scmul_base(const ec_scalar &scalar, x25519_pubkey &result_out)
{
static const mx25519_impl *impl{mx25519_select_impl(mx25519_type::MX25519_TYPE_AUTO)};
mx25519_scmul_base(impl, &result_out, reinterpret_cast<const mx25519_privkey*>(&scalar));
}
//-------------------------------------------------------------------------------------------------------------------
void x25519_scmul_key(const ec_scalar &scalar, const x25519_pubkey &pubkey, x25519_pubkey &result_out)
{
static const mx25519_impl *impl{mx25519_select_impl(mx25519_type::MX25519_TYPE_AUTO)};
mx25519_scmul_key(impl, &result_out, reinterpret_cast<const mx25519_privkey*>(&scalar), &pubkey);
}
//-------------------------------------------------------------------------------------------------------------------
void x25519_invmul_key(std::vector<ec_scalar> privkeys_to_invert,
const x25519_pubkey &initial_pubkey,
x25519_pubkey &result_out)
{
// 1. (1/({privkey1 * privkey2 * ...}))
// note: mx25519_invkey() will error if the resulting X25519 scalar is >= 2^255, so we 'search' for a valid solution
crypto::secret_key inverted_xkey;
result_out = initial_pubkey;
while (mx25519_invkey(reinterpret_cast<mx25519_privkey*>(&inverted_xkey),
reinterpret_cast<const mx25519_privkey*>(privkeys_to_invert.data()),
privkeys_to_invert.size()) != 0)
{
privkeys_to_invert.emplace_back(X25519_EIGHT); //add 8 to keys to invert
x25519_scmul_key(X25519_EIGHT, result_out, result_out); //xK = 8 * xK
}
// 2. (1/([8*8*...*8] * {privkey1 * privkey2 * ...})) * [8*8*...*8] * xK
x25519_scmul_key(inverted_xkey, result_out, result_out);
}
//-------------------------------------------------------------------------------------------------------------------
} //namespace crypto

View File

@ -1,106 +0,0 @@
// Copyright (c) 2022, 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.
// Interface for an x25519 implementation (mx25519).
#pragma once
//local headers
#include "crypto.h"
#include "generic-ops.h"
#include "memwipe.h"
#include "mlocker.h"
//third party headers
//standard headers
#include <vector>
//forward declarations
namespace crypto
{
extern "C"
{
#include "mx25519.h"
}
struct x25519_pubkey : public mx25519_pubkey
{
x25519_pubkey() = default;
x25519_pubkey(const mx25519_pubkey &other) { *this = other; }
x25519_pubkey& operator=(const mx25519_pubkey &other) { memcpy(data, other.data, 32); return *this; }
};
/**
* brief: x25519_secret_key_gen - generate a random x25519 privkey
* return: random canonical x25519 privkey
*/
secret_key x25519_secret_key_gen();
/**
* brief: x25519_pubkey_gen - generate a random x25519 pubkey
* return: random x25519 pubkey
*/
x25519_pubkey x25519_pubkey_gen();
/**
* brief: x25519_scalar_is_canonical - check that an X25519 scalar is canonical
* - expect: 2^255 > scalar >= 8 (i.e. last bit and first three bits not set)
* result: true if input scalar is canonical
*/
bool x25519_scalar_is_canonical(const ec_scalar &test_scalar);
/**
* brief: x25519_scmul_base - compute scalar * xG
* param: scalar - scalar to multiply
* result: scalar * xG
*/
void x25519_scmul_base(const ec_scalar &scalar, x25519_pubkey &result_out);
/**
* brief: x25519_scmul_key - compute scalar * pubkey
* param: scalar - scalar to multiply
* param: pubkey - public key to multiple against
* result: scalar * pubkey
*/
void x25519_scmul_key(const ec_scalar &scalar, const x25519_pubkey &pubkey, x25519_pubkey &result_out);
/**
* brief: x25519_invmul_key - compute (1/({privkey1 * privkey2 * ...})) * initial_pubkey
* param: privkeys_to_invert - {privkey1, privkey2, ...}
* param: initial_pubkey - base key for inversion
* result: (1/({privkey1 * privkey2 * ...})) * initial_pubkey
*/
void x25519_invmul_key(std::vector<ec_scalar> privkeys_to_invert,
const x25519_pubkey &initial_pubkey,
x25519_pubkey &result_out);
} //namespace crypto
inline const unsigned char* to_bytes(const crypto::x25519_pubkey &point) { return &reinterpret_cast<const unsigned char&>(point); }
/// upgrade x25519 keys
CRYPTO_MAKE_HASHABLE(x25519_pubkey)

View File

@ -33,7 +33,6 @@
#include "carrot_core/enote_utils.h" #include "carrot_core/enote_utils.h"
#include "carrot_core/payment_proposal.h" #include "carrot_core/payment_proposal.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/x25519.h"
#include "device/device.hpp" #include "device/device.hpp"
#include "performance_tests.h" #include "performance_tests.h"
#include "ringct/rctOps.h" #include "ringct/rctOps.h"
@ -222,7 +221,7 @@ public:
m_encrypted_payment_id); m_encrypted_payment_id);
m_enote = output_proposal.enote; m_enote = output_proposal.enote;
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
carrot::make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming, carrot::make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming,
m_enote.enote_ephemeral_pubkey, m_enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);
@ -266,7 +265,7 @@ public:
bool test() bool test()
{ {
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
carrot::make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming, carrot::make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming,
m_enote.enote_ephemeral_pubkey, m_enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);

View File

@ -43,8 +43,10 @@ using namespace carrot;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
namespace
{
// https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c#L17 // https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c#L17
static const crypto::x25519_pubkey x25519_small_order_points[7] = { static const mx25519_pubkey x25519_small_order_points[7] = {
/* 0 (order 4) */ /* 0 (order 4) */
{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -75,7 +77,7 @@ using namespace carrot;
{{ 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, {{ 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }} 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }}
}; };
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
struct mock_carrot_keys struct mock_carrot_keys
@ -173,7 +175,7 @@ static void unittest_scan_enote_set(const std::vector<CarrotEnoteV1> &enotes,
const CarrotEnoteV1 &enote = enotes.at(output_index); const CarrotEnoteV1 &enote = enotes.at(output_index);
// s_sr = k_v D_e // s_sr = k_v D_e
crypto::x25519_pubkey s_sr; mx25519_pubkey s_sr;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view, enote.enote_ephemeral_pubkey, s_sr); make_carrot_uncontextualized_shared_key_receiver(keys.k_view, enote.enote_ephemeral_pubkey, s_sr);
unittest_carrot_scan_result_t scan_result{}; unittest_carrot_scan_result_t scan_result{};
@ -218,6 +220,11 @@ static void unittest_scan_enote_set(const std::vector<CarrotEnoteV1> &enotes,
res.push_back(scan_result); res.push_back(scan_result);
} }
} }
} // namespace
static inline bool operator==(const mx25519_pubkey &a, const mx25519_pubkey &b)
{
return 0 == memcmp(&a, &b, sizeof(mx25519_pubkey));
}
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
TEST(carrot_core, ECDH_cryptonote_completeness) TEST(carrot_core, ECDH_cryptonote_completeness)
@ -227,13 +234,13 @@ TEST(carrot_core, ECDH_cryptonote_completeness)
crypto::secret_key k_ephem = rct::rct2sk(rct::skGen()); crypto::secret_key k_ephem = rct::rct2sk(rct::skGen());
ASSERT_NE(k_view, k_ephem); ASSERT_NE(k_view, k_ephem);
crypto::x25519_pubkey enote_ephemeral_pubkey; mx25519_pubkey enote_ephemeral_pubkey;
make_carrot_enote_ephemeral_pubkey_cryptonote(k_ephem, enote_ephemeral_pubkey); make_carrot_enote_ephemeral_pubkey_cryptonote(k_ephem, enote_ephemeral_pubkey);
crypto::x25519_pubkey s_sr_sender; mx25519_pubkey s_sr_sender;
ASSERT_TRUE(make_carrot_uncontextualized_shared_key_sender(k_ephem, view_pubkey, s_sr_sender)); ASSERT_TRUE(make_carrot_uncontextualized_shared_key_sender(k_ephem, view_pubkey, s_sr_sender));
crypto::x25519_pubkey s_sr_receiver; mx25519_pubkey s_sr_receiver;
ASSERT_TRUE(make_carrot_uncontextualized_shared_key_receiver(k_view, enote_ephemeral_pubkey, s_sr_receiver)); ASSERT_TRUE(make_carrot_uncontextualized_shared_key_receiver(k_view, enote_ephemeral_pubkey, s_sr_receiver));
EXPECT_EQ(s_sr_sender, s_sr_receiver); EXPECT_EQ(s_sr_sender, s_sr_receiver);
@ -247,13 +254,13 @@ TEST(carrot_core, ECDH_subaddress_completeness)
crypto::secret_key k_ephem = rct::rct2sk(rct::skGen()); crypto::secret_key k_ephem = rct::rct2sk(rct::skGen());
ASSERT_NE(k_view, k_ephem); ASSERT_NE(k_view, k_ephem);
crypto::x25519_pubkey enote_ephemeral_pubkey; mx25519_pubkey enote_ephemeral_pubkey;
make_carrot_enote_ephemeral_pubkey_subaddress(k_ephem, spend_pubkey, enote_ephemeral_pubkey); make_carrot_enote_ephemeral_pubkey_subaddress(k_ephem, spend_pubkey, enote_ephemeral_pubkey);
crypto::x25519_pubkey s_sr_sender; mx25519_pubkey s_sr_sender;
ASSERT_TRUE(make_carrot_uncontextualized_shared_key_sender(k_ephem, view_pubkey, s_sr_sender)); ASSERT_TRUE(make_carrot_uncontextualized_shared_key_sender(k_ephem, view_pubkey, s_sr_sender));
crypto::x25519_pubkey s_sr_receiver; mx25519_pubkey s_sr_receiver;
ASSERT_TRUE(make_carrot_uncontextualized_shared_key_receiver(k_view, enote_ephemeral_pubkey, s_sr_receiver)); ASSERT_TRUE(make_carrot_uncontextualized_shared_key_receiver(k_view, enote_ephemeral_pubkey, s_sr_receiver));
EXPECT_EQ(s_sr_sender, s_sr_receiver); EXPECT_EQ(s_sr_sender, s_sr_receiver);
@ -261,15 +268,18 @@ TEST(carrot_core, ECDH_subaddress_completeness)
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
TEST(carrot_core, ECDH_mx25519_convergence) TEST(carrot_core, ECDH_mx25519_convergence)
{ {
const crypto::x25519_pubkey P = crypto::x25519_pubkey_gen(); const mx25519_pubkey P = gen_x25519_pubkey();
const crypto::secret_key a = rct::rct2sk(rct::skGen()); const crypto::secret_key a = rct::rct2sk(rct::skGen());
const mx25519_impl *impl = mx25519_select_impl(MX25519_TYPE_AUTO);
ASSERT_NE(nullptr, impl);
// do Q = a * P using mx25519 // do Q = a * P using mx25519
crypto::x25519_pubkey Q_mx25519; mx25519_pubkey Q_mx25519;
crypto::x25519_scmul_key(a, P, Q_mx25519); mx25519_scmul_key(impl, &Q_mx25519, reinterpret_cast<const mx25519_privkey*>(&a), &P);
// do Q = a * P using make_carrot_uncontextualized_shared_key_receiver() // do Q = a * P using make_carrot_uncontextualized_shared_key_receiver()
crypto::x25519_pubkey Q_carrot; mx25519_pubkey Q_carrot;
ASSERT_TRUE(make_carrot_uncontextualized_shared_key_receiver(a, P, Q_carrot)); ASSERT_TRUE(make_carrot_uncontextualized_shared_key_receiver(a, P, Q_carrot));
// check equal // check equal
@ -302,7 +312,7 @@ TEST(carrot_core, main_address_normal_scan_completeness)
const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor)); const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor));
ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment); ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment);
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view, make_carrot_uncontextualized_shared_key_receiver(keys.k_view,
enote_proposal.enote.enote_ephemeral_pubkey, enote_proposal.enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);
@ -379,7 +389,7 @@ TEST(carrot_core, subaddress_normal_scan_completeness)
const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor)); const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor));
ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment); ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment);
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view, make_carrot_uncontextualized_shared_key_receiver(keys.k_view,
enote_proposal.enote.enote_ephemeral_pubkey, enote_proposal.enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);
@ -464,7 +474,7 @@ TEST(carrot_core, integrated_address_normal_scan_completeness)
const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor)); const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor));
ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment); ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment);
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view, make_carrot_uncontextualized_shared_key_receiver(keys.k_view,
enote_proposal.enote.enote_ephemeral_pubkey, enote_proposal.enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);
@ -523,7 +533,7 @@ TEST(carrot_core, main_address_special_scan_completeness)
.destination_address_spend_pubkey = keys.account_spend_pubkey, .destination_address_spend_pubkey = keys.account_spend_pubkey,
.amount = crypto::rand<rct::xmr_amount>(), .amount = crypto::rand<rct::xmr_amount>(),
.enote_type = enote_type, .enote_type = enote_type,
.enote_ephemeral_pubkey = crypto::x25519_pubkey_gen(), .enote_ephemeral_pubkey = gen_x25519_pubkey(),
}; };
const crypto::key_image tx_first_key_image = rct::rct2ki(rct::pkGen()); const crypto::key_image tx_first_key_image = rct::rct2ki(rct::pkGen());
@ -539,7 +549,7 @@ TEST(carrot_core, main_address_special_scan_completeness)
const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor)); const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor));
ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment); ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment);
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view, make_carrot_uncontextualized_shared_key_receiver(keys.k_view,
enote_proposal.enote.enote_ephemeral_pubkey, enote_proposal.enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);
@ -607,7 +617,7 @@ TEST(carrot_core, subaddress_special_scan_completeness)
.destination_address_spend_pubkey = subaddress.address_spend_pubkey, .destination_address_spend_pubkey = subaddress.address_spend_pubkey,
.amount = crypto::rand<rct::xmr_amount>(), .amount = crypto::rand<rct::xmr_amount>(),
.enote_type = enote_type, .enote_type = enote_type,
.enote_ephemeral_pubkey = crypto::x25519_pubkey_gen(), .enote_ephemeral_pubkey = gen_x25519_pubkey(),
}; };
const crypto::key_image tx_first_key_image = rct::rct2ki(rct::pkGen()); const crypto::key_image tx_first_key_image = rct::rct2ki(rct::pkGen());
@ -623,7 +633,7 @@ TEST(carrot_core, subaddress_special_scan_completeness)
const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor)); const rct::key recomputed_amount_commitment = rct::commit(enote_proposal.amount, rct::sk2rct(enote_proposal.amount_blinding_factor));
ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment); ASSERT_EQ(enote_proposal.enote.amount_commitment, recomputed_amount_commitment);
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view, make_carrot_uncontextualized_shared_key_receiver(keys.k_view,
enote_proposal.enote.enote_ephemeral_pubkey, enote_proposal.enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);
@ -696,7 +706,7 @@ TEST(carrot_core, main_address_internal_scan_completeness)
.destination_address_spend_pubkey = main_address.address_spend_pubkey, .destination_address_spend_pubkey = main_address.address_spend_pubkey,
.amount = crypto::rand<rct::xmr_amount>(), .amount = crypto::rand<rct::xmr_amount>(),
.enote_type = enote_type, .enote_type = enote_type,
.enote_ephemeral_pubkey = crypto::x25519_pubkey_gen(), .enote_ephemeral_pubkey = gen_x25519_pubkey(),
.internal_message = gen_janus_anchor() .internal_message = gen_janus_anchor()
}; };
@ -772,7 +782,7 @@ TEST(carrot_core, subaddress_internal_scan_completeness)
.destination_address_spend_pubkey = subaddress.address_spend_pubkey, .destination_address_spend_pubkey = subaddress.address_spend_pubkey,
.amount = crypto::rand<rct::xmr_amount>(), .amount = crypto::rand<rct::xmr_amount>(),
.enote_type = enote_type, .enote_type = enote_type,
.enote_ephemeral_pubkey = crypto::x25519_pubkey_gen(), .enote_ephemeral_pubkey = gen_x25519_pubkey(),
.internal_message = gen_janus_anchor() .internal_message = gen_janus_anchor()
}; };
@ -859,7 +869,7 @@ TEST(carrot_core, main_address_coinbase_scan_completeness)
ASSERT_EQ(proposal.amount, enote.amount); ASSERT_EQ(proposal.amount, enote.amount);
crypto::x25519_pubkey s_sender_receiver_unctx; mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view, make_carrot_uncontextualized_shared_key_receiver(keys.k_view,
enote.enote_ephemeral_pubkey, enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx); s_sender_receiver_unctx);

View File

@ -104,7 +104,7 @@ static void unittest_legacy_scan_enote_set(const std::vector<CarrotEnoteV1> &eno
const CarrotEnoteV1 &enote = enotes.at(output_index); const CarrotEnoteV1 &enote = enotes.at(output_index);
// s_sr = k_v D_e // s_sr = k_v D_e
crypto::x25519_pubkey s_sr; mx25519_pubkey s_sr;
make_carrot_uncontextualized_shared_key_receiver(acb.get_keys().m_view_secret_key, make_carrot_uncontextualized_shared_key_receiver(acb.get_keys().m_view_secret_key,
enote.enote_ephemeral_pubkey, enote.enote_ephemeral_pubkey,
s_sr); s_sr);

View File

@ -35,12 +35,11 @@
extern "C" extern "C"
{ {
#include "crypto/crypto-ops.h" #include "crypto/crypto-ops.h"
#include "mx25519.h"
} }
#include "crypto/x25519.h"
#include "crypto/generators.h" #include "crypto/generators.h"
#include "cryptonote_basic/cryptonote_basic_impl.h" #include "cryptonote_basic/cryptonote_basic_impl.h"
#include "cryptonote_basic/merge_mining.h" #include "cryptonote_basic/merge_mining.h"
#include "mx25519.h"
#include "ringct/rctOps.h" #include "ringct/rctOps.h"
#include "ringct/rctTypes.h" #include "ringct/rctTypes.h"
#include "string_tools.h" #include "string_tools.h"
@ -59,7 +58,6 @@ namespace
"6c7251d54154cfa92c173a0dd39c1f948b655970153799af2aeadc9ff1add0ea"; "6c7251d54154cfa92c173a0dd39c1f948b655970153799af2aeadc9ff1add0ea";
template<typename T> void *addressof(T &t) { return &t; } template<typename T> void *addressof(T &t) { return &t; }
template<> void *addressof(crypto::secret_key &k) { return addressof(unwrap(unwrap(k))); }
template<typename T> template<typename T>
bool is_formatted() bool is_formatted()
@ -414,10 +412,10 @@ TEST(Crypto, x25519_impl_scmul_key_convergence)
dump_mx25519_impls(available_impls); dump_mx25519_impls(available_impls);
crypto::x25519_pubkey P_fixed; mx25519_pubkey P_fixed;
epee::string_tools::hex_to_pod("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", P_fixed); epee::string_tools::hex_to_pod("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", P_fixed);
crypto::x25519_pubkey P_random; mx25519_pubkey P_random;
rct::key tmp = rct::pkGen(); rct::key tmp = rct::pkGen();
edwards_bytes_to_x25519_vartime(P_random.data, tmp.bytes); edwards_bytes_to_x25519_vartime(P_random.data, tmp.bytes);
@ -541,9 +539,9 @@ TEST(Crypto, x25519_secret_key_8_scmul_base)
TEST(Crypto, ConvertPointE_Base) TEST(Crypto, ConvertPointE_Base)
{ {
const crypto::public_key G = crypto::get_G(); const crypto::public_key G = crypto::get_G();
const crypto::x25519_pubkey B_expected = {{9}}; const mx25519_pubkey B_expected = {{9}};
crypto::x25519_pubkey B_actual; mx25519_pubkey B_actual;
edwards_bytes_to_x25519_vartime(B_actual.data, to_bytes(G)); edwards_bytes_to_x25519_vartime(B_actual.data, to_bytes(G));
EXPECT_EQ(B_expected, B_actual); EXPECT_EQ(B_expected, B_actual);
@ -551,6 +549,10 @@ TEST(Crypto, ConvertPointE_Base)
TEST(Crypto, ConvertPointE_PreserveScalarMultBase) 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 // *clamped* private key a
const crypto::secret_key a = rct::rct2sk(rct::skGen()); const crypto::secret_key a = rct::rct2sk(rct::skGen());
rct::key a_key; rct::key a_key;
@ -560,21 +562,26 @@ TEST(Crypto, ConvertPointE_PreserveScalarMultBase)
const rct::key P_edward = rct::scalarmultBase(a_key); const rct::key P_edward = rct::scalarmultBase(a_key);
// P_mont = a B // P_mont = a B
crypto::x25519_pubkey P_mont; mx25519_pubkey P_mont;
crypto::x25519_scmul_base(a, P_mont); mx25519_scmul_base(impl, &P_mont, reinterpret_cast<const mx25519_privkey*>(&a));
// P_mont' = ConvertPointE(P_ed) // P_mont' = ConvertPointE(P_ed)
crypto::x25519_pubkey P_mont_converted; mx25519_pubkey P_mont_converted;
edwards_bytes_to_x25519_vartime(P_mont_converted.data, P_edward.bytes); edwards_bytes_to_x25519_vartime(P_mont_converted.data, P_edward.bytes);
// P_mont' ?= P_mont // P_mont' ?= P_mont
EXPECT_EQ(P_mont_converted, P_mont); EXPECT_EQ(P_mont_converted, P_mont);
}
} }
TEST(Crypto, ConvertPointE_PreserveScalarMultBase_gep3) TEST(Crypto, ConvertPointE_PreserveScalarMultBase_gep3)
{ {
// compared to ConvertPointE_PreserveScalarMultBase, this test will use Z != 1 (probably) // 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()); const crypto::secret_key a = rct::rct2sk(rct::skGen());
rct::key a_key; rct::key a_key;
memcpy(&a_key, &a, sizeof(rct::key)); memcpy(&a_key, &a, sizeof(rct::key));
@ -589,15 +596,16 @@ TEST(Crypto, ConvertPointE_PreserveScalarMultBase_gep3)
ASSERT_NE(Z_bytes, rct::I); // check Z != 1 ASSERT_NE(Z_bytes, rct::I); // check Z != 1
// P_mont = a B // P_mont = a B
crypto::x25519_pubkey P_mont; mx25519_pubkey P_mont;
crypto::x25519_scmul_base(a, P_mont); mx25519_scmul_base(impl, &P_mont, reinterpret_cast<const mx25519_privkey*>(&a));
// P_mont' = ConvertPointE(P_ed) // P_mont' = ConvertPointE(P_ed)
crypto::x25519_pubkey P_mont_converted; mx25519_pubkey P_mont_converted;
ge_p3_to_x25519(P_mont_converted.data, &P_p3); ge_p3_to_x25519(P_mont_converted.data, &P_p3);
// P_mont' ?= P_mont // P_mont' ?= P_mont
EXPECT_EQ(P_mont_converted, P_mont); EXPECT_EQ(P_mont_converted, P_mont);
}
} }
TEST(Crypto, ConvertPointE_EraseSign) TEST(Crypto, ConvertPointE_EraseSign)
@ -608,10 +616,10 @@ TEST(Crypto, ConvertPointE_EraseSign)
rct::key negP; rct::key negP;
rct::subKeys(negP, rct::I, P); rct::subKeys(negP, rct::I, P);
crypto::x25519_pubkey P_mont; mx25519_pubkey P_mont;
edwards_bytes_to_x25519_vartime(P_mont.data, P.bytes); edwards_bytes_to_x25519_vartime(P_mont.data, P.bytes);
crypto::x25519_pubkey negP_mont; mx25519_pubkey negP_mont;
edwards_bytes_to_x25519_vartime(negP_mont.data, negP.bytes); edwards_bytes_to_x25519_vartime(negP_mont.data, negP.bytes);
EXPECT_EQ(P_mont, negP_mont); EXPECT_EQ(P_mont, negP_mont);