carrot_core: unbind K^j_v in d_e and overhaul scanning functions

This commit is contained in:
jeffro256
2025-04-16 17:16:18 -05:00
committed by akildemir
parent ce9c845d26
commit 2194b853d5
13 changed files with 863 additions and 563 deletions

View File

@@ -236,11 +236,11 @@ public:
rct::xmr_amount recovered_amount;
carrot::payment_id_t recovered_payment_id;
carrot::CarrotEnoteType recovered_enote_type;
if (!carrot::try_scan_carrot_enote_external(m_enote,
if (!carrot::try_scan_carrot_enote_external_receiver(m_enote,
m_encrypted_payment_id,
s_sender_receiver_unctx,
{&m_account_spend_pubkey, 1},
m_k_view_dev,
m_account_spend_pubkey,
_1,
_2,
recovered_address_spend_pubkey,
@@ -280,11 +280,11 @@ public:
rct::xmr_amount recovered_amount;
carrot::payment_id_t recovered_payment_id;
carrot::CarrotEnoteType recovered_enote_type;
const bool scan_success = carrot::try_scan_carrot_enote_external(m_enote,
const bool scan_success = carrot::try_scan_carrot_enote_external_receiver(m_enote,
m_encrypted_payment_id,
s_sender_receiver_unctx,
{&m_account_spend_pubkey, 1},
m_k_view_dev,
m_account_spend_pubkey,
_1,
_2,
recovered_address_spend_pubkey,

View File

@@ -132,11 +132,11 @@ TEST(carrot_core, main_address_normal_scan_completeness)
crypto::secret_key recovered_amount_blinding_factor;
encrypted_payment_id_t recovered_payment_id;
CarrotEnoteType recovered_enote_type;
const bool scan_success = try_scan_carrot_enote_external(enote_proposal.enote,
const bool scan_success = try_scan_carrot_enote_external_receiver(enote_proposal.enote,
encrypted_payment_id,
s_sender_receiver_unctx,
{&keys.carrot_account_spend_pubkey, 1},
keys.k_view_incoming_dev,
keys.carrot_account_spend_pubkey,
recovered_sender_extension_g,
recovered_sender_extension_t,
recovered_address_spend_pubkey,
@@ -202,11 +202,11 @@ TEST(carrot_core, subaddress_normal_scan_completeness)
crypto::secret_key recovered_amount_blinding_factor;
encrypted_payment_id_t recovered_payment_id;
CarrotEnoteType recovered_enote_type;
const bool scan_success = try_scan_carrot_enote_external(enote_proposal.enote,
const bool scan_success = try_scan_carrot_enote_external_receiver(enote_proposal.enote,
encrypted_payment_id,
s_sender_receiver_unctx,
{&keys.carrot_account_spend_pubkey, 1},
keys.k_view_incoming_dev,
keys.carrot_account_spend_pubkey,
recovered_sender_extension_g,
recovered_sender_extension_t,
recovered_address_spend_pubkey,
@@ -269,11 +269,11 @@ TEST(carrot_core, integrated_address_normal_scan_completeness)
crypto::secret_key recovered_amount_blinding_factor;
encrypted_payment_id_t recovered_payment_id;
CarrotEnoteType recovered_enote_type;
const bool scan_success = try_scan_carrot_enote_external(enote_proposal.enote,
const bool scan_success = try_scan_carrot_enote_external_receiver(enote_proposal.enote,
encrypted_payment_id,
s_sender_receiver_unctx,
{&keys.carrot_account_spend_pubkey, 1},
keys.k_view_incoming_dev,
keys.carrot_account_spend_pubkey,
recovered_sender_extension_g,
recovered_sender_extension_t,
recovered_address_spend_pubkey,
@@ -340,11 +340,11 @@ TEST(carrot_core, main_address_special_scan_completeness)
crypto::secret_key recovered_amount_blinding_factor;
encrypted_payment_id_t recovered_payment_id;
CarrotEnoteType recovered_enote_type;
const bool scan_success = try_scan_carrot_enote_external(enote_proposal.enote,
const bool scan_success = try_scan_carrot_enote_external_receiver(enote_proposal.enote,
std::nullopt,
s_sender_receiver_unctx,
{&keys.carrot_account_spend_pubkey, 1},
keys.k_view_incoming_dev,
keys.carrot_account_spend_pubkey,
recovered_sender_extension_g,
recovered_sender_extension_t,
recovered_address_spend_pubkey,
@@ -417,11 +417,11 @@ TEST(carrot_core, subaddress_special_scan_completeness)
crypto::secret_key recovered_amount_blinding_factor;
encrypted_payment_id_t recovered_payment_id;
CarrotEnoteType recovered_enote_type;
const bool scan_success = try_scan_carrot_enote_external(enote_proposal.enote,
const bool scan_success = try_scan_carrot_enote_external_receiver(enote_proposal.enote,
std::nullopt,
s_sender_receiver_unctx,
{&keys.carrot_account_spend_pubkey, 1},
keys.k_view_incoming_dev,
keys.carrot_account_spend_pubkey,
recovered_sender_extension_g,
recovered_sender_extension_t,
recovered_address_spend_pubkey,
@@ -487,7 +487,7 @@ TEST(carrot_core, main_address_internal_scan_completeness)
crypto::secret_key recovered_amount_blinding_factor;
CarrotEnoteType recovered_enote_type;
janus_anchor_t recovered_internal_message;
const bool scan_success = try_scan_carrot_enote_internal(enote_proposal.enote,
const bool scan_success = try_scan_carrot_enote_internal_receiver(enote_proposal.enote,
keys.s_view_balance_dev,
recovered_sender_extension_g,
recovered_sender_extension_t,
@@ -557,7 +557,7 @@ TEST(carrot_core, subaddress_internal_scan_completeness)
crypto::secret_key recovered_amount_blinding_factor;
CarrotEnoteType recovered_enote_type;
janus_anchor_t recovered_internal_message;
const bool scan_success = try_scan_carrot_enote_internal(enote_proposal.enote,
const bool scan_success = try_scan_carrot_enote_internal_receiver(enote_proposal.enote,
keys.s_view_balance_dev,
recovered_sender_extension_g,
recovered_sender_extension_t,
@@ -606,14 +606,19 @@ TEST(carrot_core, main_address_coinbase_scan_completeness)
ASSERT_EQ(proposal.amount, enote.amount);
mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view_incoming_dev,
enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx);
crypto::secret_key recovered_sender_extension_g;
crypto::secret_key recovered_sender_extension_t;
const bool scan_success = try_ecdh_and_scan_carrot_coinbase_enote(enote,
keys.k_view_incoming_dev,
const bool scan_success = try_scan_carrot_coinbase_enote_receiver(enote,
s_sender_receiver_unctx,
keys.carrot_account_spend_pubkey,
recovered_sender_extension_g,
recovered_sender_extension_t);
ASSERT_TRUE(scan_success);
// check spendability
@@ -677,8 +682,7 @@ static void subtest_2out_transfer_get_output_enote_proposals_completeness(const
// generate input context
const crypto::key_image tx_first_key_image = rct::rct2ki(rct::pkGen());
input_context_t input_context;
make_carrot_input_context(tx_first_key_image, input_context);
const input_context_t input_context = make_carrot_input_context(tx_first_key_image);
// outgoing payment proposal to bob
const CarrotPaymentProposalV1 bob_payment_proposal = CarrotPaymentProposalV1{

View File

@@ -110,11 +110,11 @@ static void unittest_legacy_scan_enote_set(const std::vector<CarrotEnoteV1> &eno
s_sr);
unittest_legacy_scan_result_t scan_result{};
const bool r = try_scan_carrot_enote_external(enote,
const bool r = try_scan_carrot_enote_external_receiver(enote,
encrypted_payment_id,
s_sr,
{&acb.get_keys().m_account_address.m_spend_public_key, 1},
view_incoming_key_ram_borrowed_device(acb.get_keys().m_view_secret_key),
acb.get_keys().m_account_address.m_spend_public_key,
scan_result.sender_extension_g,
scan_result.sender_extension_t,
scan_result.address_spend_pubkey,
@@ -164,8 +164,7 @@ static void subtest_legacy_2out_transfer_get_output_enote_proposals_completeness
// generate input context
const crypto::key_image tx_first_key_image = rct::rct2ki(rct::pkGen());
input_context_t input_context;
make_carrot_input_context(tx_first_key_image, input_context);
const input_context_t input_context = make_carrot_input_context(tx_first_key_image);
// outgoing payment proposal to bob
const CarrotPaymentProposalV1 bob_payment_proposal = CarrotPaymentProposalV1{

View File

@@ -305,7 +305,7 @@ void mock_scan_enote_set(const std::vector<CarrotEnoteV1> &enotes,
{
res.clear();
// We support receives to both the new and odl K^0_s
// We support receives to both the new and old K^0_s
const crypto::public_key main_address_spend_pubkeys[2] = {
keys.carrot_account_spend_pubkey,
keys.legacy_acb.get_keys().m_account_address.m_spend_public_key
@@ -324,11 +324,11 @@ void mock_scan_enote_set(const std::vector<CarrotEnoteV1> &enotes,
mock_scan_result_t scan_result{};
scan_result.output_index = output_index;
if (try_scan_carrot_enote_external(enote,
if (try_scan_carrot_enote_external_receiver(enote,
encrypted_payment_id,
s_sr,
keys.k_view_incoming_dev,
{main_address_spend_pubkeys, 2},
keys.k_view_incoming_dev,
scan_result.sender_extension_g,
scan_result.sender_extension_t,
scan_result.address_spend_pubkey,
@@ -348,7 +348,7 @@ void mock_scan_enote_set(const std::vector<CarrotEnoteV1> &enotes,
const CarrotEnoteV1 &enote = enotes.at(output_index);
mock_scan_result_t scan_result{};
const bool r = try_scan_carrot_enote_internal(enote,
const bool r = try_scan_carrot_enote_internal_receiver(enote,
keys.s_view_balance_dev,
scan_result.sender_extension_g,
scan_result.sender_extension_t,
@@ -372,6 +372,12 @@ void mock_scan_coinbase_enote_set(const std::vector<CarrotCoinbaseEnoteV1> &coin
{
res.clear();
// We support receives to both the new and old K^0_s
const crypto::public_key main_address_spend_pubkeys[2] = {
keys.carrot_account_spend_pubkey,
keys.legacy_acb.get_keys().m_account_address.m_spend_public_key
};
for (size_t output_index = 0; output_index < coinbase_enotes.size(); ++output_index)
{
const CarrotCoinbaseEnoteV1 &enote = coinbase_enotes.at(output_index);
@@ -384,27 +390,18 @@ void mock_scan_coinbase_enote_set(const std::vector<CarrotCoinbaseEnoteV1> &coin
scan_result.enote_type = CarrotEnoteType::PAYMENT;
scan_result.internal_message = janus_anchor_t{};
if (try_ecdh_and_scan_carrot_coinbase_enote(enote,
keys.k_view_incoming_dev,
keys.carrot_account_spend_pubkey,
scan_result.sender_extension_g,
scan_result.sender_extension_t))
{
scan_result.address_spend_pubkey = keys.carrot_account_spend_pubkey;
res.push_back(scan_result);
continue;
}
mx25519_pubkey s_sender_receiver_unctx;
make_carrot_uncontextualized_shared_key_receiver(keys.k_view_incoming_dev,
enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx);
// We do a double external scan here to check anchor_sp against both the legacy K_s
// and new K_s. This is inefficient and less secure against Janus attacks, but it allows
// completeness for now when we use hybrid key structures
if (try_ecdh_and_scan_carrot_coinbase_enote(coinbase_enotes.at(output_index),
keys.k_view_incoming_dev,
keys.legacy_acb.get_keys().m_account_address.m_spend_public_key,
if (try_scan_carrot_coinbase_enote_receiver(enote,
s_sender_receiver_unctx,
{main_address_spend_pubkeys, 2},
scan_result.sender_extension_g,
scan_result.sender_extension_t))
scan_result.sender_extension_t,
scan_result.address_spend_pubkey))
{
scan_result.address_spend_pubkey = keys.legacy_acb.get_keys().m_account_address.m_spend_public_key;
res.push_back(scan_result);
continue;
}