Skip to content

Commit

Permalink
jamtis changes
Browse files Browse the repository at this point in the history
* nominal address tag protection for LWs (extra address key)
* flexible view tags
* churning and pocketchange protection for LWs (auxiliary enote records)
  • Loading branch information
jeffro256 committed May 24, 2024
1 parent ace9228 commit 537ba29
Show file tree
Hide file tree
Showing 73 changed files with 2,744 additions and 2,530 deletions.
4 changes: 4 additions & 0 deletions src/crypto/x25519.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ void x25519_invmul_key(std::vector<x25519_secret_key> privkeys_to_invert,

} //namespace crypto

inline const unsigned char* to_bytes(const crypto::x25519_pubkey &point) { return &reinterpret_cast<const unsigned char&>(point); }
inline const unsigned char* to_bytes(const crypto::x25519_scalar &scalar) { return &reinterpret_cast<const unsigned char&>(scalar); }
inline const unsigned char* to_bytes(const crypto::x25519_secret_key &skey) { return &reinterpret_cast<const unsigned char&>(skey); }

/// upgrade x25519 keys
CRYPTO_MAKE_HASHABLE(x25519_pubkey)
CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(x25519_scalar)
Expand Down
19 changes: 11 additions & 8 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,27 +306,30 @@ namespace config
const constexpr char HASH_KEY_BINNED_REF_SET_MEMBER[] = "binned_refset_member";

const constexpr char HASH_KEY_JAMTIS_VIEWBALANCE_KEY[] = "jamtis_view_balance_key";
const constexpr char HASH_KEY_JAMTIS_UNLOCKAMOUNTS_KEY[] = "jamtis_unlock_amounts_key";
const constexpr char HASH_KEY_JAMTIS_VIEWRECEIVED_KEY[] = "jamtis_view_received_key";
const constexpr char HASH_KEY_JAMTIS_GENERATEADDRESS_SECRET[] = "jamtis_generate_address_secret";
const constexpr char HASH_KEY_JAMTIS_CIPHERTAG_SECRET[] = "jamtis_cipher_tag_secret";
const constexpr char HASH_KEY_JAMTIS_FINDRECEIVED_KEY[] = "jamtis_find_received_key";
const constexpr char HASH_KEY_JAMTIS_FILTERASSIST_KEY[] = "jamtis_filter_assist_key";
const constexpr char HASH_KEY_JAMTIS_INDEX_EXTENSION_GENERATOR[] = "jamtis_index_extension_generator";
const constexpr char HASH_KEY_JAMTIS_ADDRESS_PRIVKEY[] = "jamtis_address_privkey";
const constexpr char HASH_KEY_JAMTIS_SPENDKEY_EXTENSION_G[] = "jamtis_spendkey_extension_g";
const constexpr char HASH_KEY_JAMTIS_SPENDKEY_EXTENSION_X[] = "jamtis_spendkey_extension_x";
const constexpr char HASH_KEY_JAMTIS_SPENDKEY_EXTENSION_U[] = "jamtis_spendkey_extension_u";
const constexpr char HASH_KEY_JAMTIS_ADDRESS_TAG_HINT[] = "jamtis_address_tag_hint";
const constexpr char HASH_KEY_JAMTIS_ENCRYPTED_ADDRESS_TAG[] = "jamtis_encrypted_address_tag";
const constexpr char HASH_KEY_JAMTIS_VIEW_TAG[] = "jamtis_view_tag";
const constexpr char HASH_KEY_JAMTIS_VIEW_TAG_PRIMARY[] = "jamtis_view_tag_primary";
const constexpr char HASH_KEY_JAMTIS_VIEW_TAG_COMPLEMENTARY[] = "jamtis_view_tag_complementary";
const constexpr char HASH_KEY_JAMTIS_VIEW_TAG_AUXILIARY[] = "jamtis_view_tag_auxiliary";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_PLAIN[] = "jamtis_sr_secret_plain";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_DUMMY[] = "jamtis_selfsend_dummy";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_CHANGE[] = "jamtis_selfsend_change";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_SELF_SPEND[] = "jamtis_selfsend_self_spend";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_EXCLUSIVE[] = "jamtis_selfsend_exclusive_secret";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_AUXILIARY[] = "jamtis_selfsend_auxiliary_secret";
const constexpr char HASH_KEY_JAMTIS_SENDER_ONETIME_ADDRESS_EXTENSION_G[] = "jamtis_sender_extension_g";
const constexpr char HASH_KEY_JAMTIS_SENDER_ONETIME_ADDRESS_EXTENSION_X[] = "jamtis_sender_extension_x";
const constexpr char HASH_KEY_JAMTIS_SENDER_ONETIME_ADDRESS_EXTENSION_U[] = "jamtis_sender_extension_u";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_PLAIN[] = "jamtis_amount_baked_key_plain";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_SELFSEND[] = "jamtis_amount_baked_key_selfsend";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_EXCLUSIVE_SELFSPEND[] = "jamtis_amount_baked_key_ex_selfspend";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_EXCLUSIVE_CHANGE[] = "jamtis_amount_baked_key_ex_change";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_AUXILIARY_SELFSPEND[] = "jamtis_amount_baked_key_aux_selfspend";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_AUXILIARY_CHANGE[] = "jamtis_amount_baked_key_aux_change";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BLINDING_FACTOR[] = "jamtis_amount_commitment_blinding_factor";
const constexpr char HASH_KEY_JAMTIS_ENCODED_AMOUNT_MASK[] = "jamtis_encoded_amount_mask";
const constexpr char HASH_KEY_JAMTIS_INPUT_CONTEXT_COINBASE[] = "jamtis_input_context_coinbase";
Expand Down
2 changes: 1 addition & 1 deletion src/seraphis_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ set(seraphis_core_sources
binned_reference_set.cpp
binned_reference_set_utils.cpp
discretized_fee.cpp
jamtis_account_secrets.cpp
jamtis_address_tag_utils.cpp
jamtis_address_utils.cpp
jamtis_core_utils.cpp
jamtis_destination.cpp
jamtis_enote_utils.cpp
jamtis_payment_proposal.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//paired header
#include "jamtis_core_utils.h"
#include "jamtis_account_secrets.h"

//local headers
#include "crypto/crypto.h"
Expand Down Expand Up @@ -59,43 +59,51 @@ void make_jamtis_viewbalance_key(const crypto::secret_key &k_master,
sp_derive_key(to_bytes(k_master), transcript.data(), transcript.size(), to_bytes(k_view_balance_out));
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_unlockamounts_key(const crypto::secret_key &k_view_balance,
crypto::x25519_secret_key &xk_unlock_amounts_out)
void make_jamtis_viewreceived_key(const crypto::secret_key &k_view_balance,
crypto::x25519_secret_key &d_view_received_out)
{
// xk_ua = H_n_x25519[k_vb]()
SpKDFTranscript transcript{config::HASH_KEY_JAMTIS_UNLOCKAMOUNTS_KEY, 0};
sp_derive_x25519_key(to_bytes(k_view_balance), transcript.data(), transcript.size(), xk_unlock_amounts_out.data);
// d_vr = H_n_x25519[k_vb]()
SpKDFTranscript transcript{config::HASH_KEY_JAMTIS_VIEWRECEIVED_KEY, 0};
sp_derive_x25519_key(to_bytes(k_view_balance), transcript.data(), transcript.size(), d_view_received_out.data);
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_unlockamounts_pubkey(const crypto::x25519_secret_key &xk_unlock_amounts,
crypto::x25519_pubkey &unlockamounts_pubkey_out)
void make_jamtis_exchangebase_pubkey(const crypto::x25519_secret_key &d_view_received,
crypto::x25519_pubkey &exchangebase_pubkey_out)
{
// xK_ua = xk_ua * xG
x25519_scmul_base(xk_unlock_amounts, unlockamounts_pubkey_out);
// D_base = d_vr * xG
x25519_scmul_base(d_view_received, exchangebase_pubkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_findreceived_key(const crypto::secret_key &k_view_balance,
crypto::x25519_secret_key &xk_find_received_out)
void make_jamtis_viewreceived_pubkey(const crypto::x25519_secret_key &d_view_received,
const crypto::x25519_pubkey &exchangebase_pubkey,
crypto::x25519_pubkey &viewreceived_pubkey_out)
{
// xk_fr = H_n_x25519[k_vb]()
SpKDFTranscript transcript{config::HASH_KEY_JAMTIS_FINDRECEIVED_KEY, 0};
sp_derive_x25519_key(to_bytes(k_view_balance), transcript.data(), transcript.size(), xk_find_received_out.data);
// D_vr = d_vr * D_base
x25519_scmul_key(d_view_received, exchangebase_pubkey, viewreceived_pubkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_findreceived_pubkey(const crypto::x25519_secret_key &xk_find_received,
const crypto::x25519_pubkey &unlockamounts_pubkey,
crypto::x25519_pubkey &findreceived_pubkey_out)
void make_jamtis_filterassist_key(const crypto::x25519_secret_key &d_view_received,
crypto::x25519_secret_key &d_filter_assist_out)
{
// xK_fr = xk_fr * xK_ua
x25519_scmul_key(xk_find_received, unlockamounts_pubkey, findreceived_pubkey_out);
// d_fa = H_n_x25519[d_vr]()
SpKDFTranscript transcript{config::HASH_KEY_JAMTIS_FILTERASSIST_KEY, 0};
sp_derive_x25519_key(to_bytes(d_view_received), transcript.data(), transcript.size(), d_filter_assist_out.data);
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_generateaddress_secret(const crypto::secret_key &k_view_balance,
void make_jamtis_filterassist_pubkey(const crypto::x25519_secret_key &d_filter_assist,
const crypto::x25519_pubkey &exchangebase_pubkey,
crypto::x25519_pubkey &filterassist_pubkey_out)
{
// D_fa = d_fa * D_base
x25519_scmul_key(d_filter_assist, exchangebase_pubkey, filterassist_pubkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_generateaddress_secret(const crypto::x25519_secret_key &d_view_received,
crypto::secret_key &s_generate_address_out)
{
// s_ga = H_32[k_vb]()
// s_ga = H_32[d_vr]()
SpKDFTranscript transcript{config::HASH_KEY_JAMTIS_GENERATEADDRESS_SECRET, 0};
sp_derive_secret(to_bytes(k_view_balance), transcript.data(), transcript.size(), to_bytes(s_generate_address_out));
sp_derive_secret(to_bytes(d_view_received), transcript.data(), transcript.size(), to_bytes(s_generate_address_out));
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_ciphertag_secret(const crypto::secret_key &s_generate_address,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,47 +60,56 @@ namespace jamtis
void make_jamtis_viewbalance_key(const crypto::secret_key &k_master,
crypto::secret_key &k_view_balance_out);
/**
* brief: make_jamtis_unlockamounts_key - unlock-amounts key, for recovering amounts and reconstructing amount commitments
* xk_ua = H_n_x25519[k_vb]()
* brief: make_jamtis_viewreceived_key - view-received key, for locating and viewing amounts of normal enotes
* d_vr = H_n_x25519[k_vb]()
* param: k_view_balance - k_vb
* outparam: xk_unlock_amounts_out - xk_ua
* outparam: d_view_received_out - d_vr
*/
void make_jamtis_unlockamounts_key(const crypto::secret_key &k_view_balance,
crypto::x25519_secret_key &xk_unlock_amounts_out);
void make_jamtis_viewreceived_key(const crypto::secret_key &k_view_balance,
crypto::x25519_secret_key &d_view_received_out);
/**
* brief: make_jamtis_unlockamounts_pubkey - xK_ua
* - xK_ua = xk_ua * xG
* param: xk_unlock_amounts - xk_ua
* outparam: unlockamounts_pubkey_out - xK_ua
* brief make_jamtis_exchangebase_pubkey - D_base
* D_base = d_vr * xG
* param: d_view_received - d_vr
* outparam: exchangebase_pubkey_out
*/
void make_jamtis_exchangebase_pubkey(const crypto::x25519_secret_key &d_view_received,
crypto::x25519_pubkey &exchangebase_pubkey_out);
/**
* brief: make_jamtis_viewreceived_pubkey - D_vr
* - D_vr = D_vr * D_base
* param: d_view_received - d_vr
* param: exchangebase_pubkey - D_base
* outparam: viewreceived_pubkey_out - D_vr
*/
void make_jamtis_unlockamounts_pubkey(const crypto::x25519_secret_key &xk_unlock_amounts,
crypto::x25519_pubkey &unlockamounts_pubkey_out);
void make_jamtis_viewreceived_pubkey(const crypto::x25519_secret_key &d_view_received,
const crypto::x25519_pubkey &exchangebase_pubkey,
crypto::x25519_pubkey &viewreceived_pubkey_out);
/**
* brief: make_jamtis_findreceived_key - find-received key, for finding enotes received by the wallet
* - use to compute view tags and nominal spend keys
* xk_fr = H_n_x25519[k_vb]()
* param: k_view_balance - k_vb
* outparam: xk_find_received_out - xk_fr
* brief: make_jamtis_filterassist_key - filter-assist key, for calculating primary view tags
* d_fa = H_n_x25519[d_vr]()
* param: d_view_received - d_vr
* outparam: d_filter_assist_out - d_fa
*/
void make_jamtis_findreceived_key(const crypto::secret_key &k_view_balance,
crypto::x25519_secret_key &xk_find_received_out);
void make_jamtis_filterassist_key(const crypto::x25519_secret_key &d_view_received,
crypto::x25519_secret_key &d_filter_assist_out);
/**
* brief: make_jamtis_findreceived_pubkey - xK_fr
* - xK_fr = xk_fr * xK_ua
* param: xk_find_received - xk_fr
* param: unlockamounts_pubkey - xK_ua
* outparam: findreceived_pubkey_out - xK_fr
* brief: make_jamtis_filterassist_pubkey - D_fa
* - D_fa = d_fa * D_base
* param: d_filter_assist - d_fa
* param: exchangebase_pubkey - D_base
* outparam: filterassist_pubky_out - D_fa
*/
void make_jamtis_findreceived_pubkey(const crypto::x25519_secret_key &xk_find_received,
const crypto::x25519_pubkey &unlockamounts_pubkey,
crypto::x25519_pubkey &findreceived_pubkey_out);
void make_jamtis_filterassist_pubkey(const crypto::x25519_secret_key &d_filter_assist,
const crypto::x25519_pubkey &exchangebase_pubkey,
crypto::x25519_pubkey &filterassist_pubkey_out);
/**
* brief: make_jamtis_generateaddress_secret - generate-address secret, for generating addresses
* s_ga = H_32[k_vb]()
* param: k_view_balance - k_vb
* s_ga = H_32[d_vr]()
* param: d_view_received - d_vr
* outparam: s_generate_address_out - s_ga
*/
void make_jamtis_generateaddress_secret(const crypto::secret_key &k_view_balance,
void make_jamtis_generateaddress_secret(const crypto::x25519_secret_key &d_view_received,
crypto::secret_key &s_generate_address_out);
/**
* brief: make_jamtis_ciphertag_secret - cipher-tag secret, for ciphering address indices to/from address tags
Expand Down
67 changes: 9 additions & 58 deletions src/seraphis_core/jamtis_address_tag_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,48 +87,8 @@ static encrypted_address_tag_secret_t get_encrypted_address_tag_secret(const rct
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
static address_tag_hint_t get_address_tag_hint(const crypto::secret_key &cipher_key,
const address_index_t &encrypted_address_index)
{
static_assert(sizeof(address_tag_hint_t) == 2, "");
static_assert(sizeof(config::TRANSCRIPT_PREFIX) != 0, "");
static_assert(sizeof(config::HASH_KEY_JAMTIS_ADDRESS_TAG_HINT) != 0, "");

// assemble hash contents: prefix || 'domain-sep' || k || cipher[k](j)
// note: use a raw C-style struct here instead of SpKDFTranscript for maximal performance (the string produced is
// equivalent to what you'd get from SpKDFTranscript)
// note2: '-1' removes the null terminator
struct hash_context_t {
unsigned char prefix[sizeof(config::TRANSCRIPT_PREFIX) - 1];
unsigned char domain_separator[sizeof(config::HASH_KEY_JAMTIS_ADDRESS_TAG_HINT) - 1];
rct::key cipher_key; //not crypto::secret_key, which has significant construction cost
address_index_t enc_j;
} hash_context;
static_assert(!epee::has_padding<hash_context_t>(), "");

memcpy(hash_context.prefix, config::TRANSCRIPT_PREFIX, sizeof(config::TRANSCRIPT_PREFIX) - 1);
memcpy(hash_context.domain_separator,
config::HASH_KEY_JAMTIS_ADDRESS_TAG_HINT,
sizeof(config::HASH_KEY_JAMTIS_ADDRESS_TAG_HINT) - 1);
hash_context.cipher_key = rct::sk2rct(cipher_key);
hash_context.enc_j = encrypted_address_index;

// address_tag_hint = H_2(k, cipher[k](j))
address_tag_hint_t address_tag_hint;
sp_hash_to_2(&hash_context, sizeof(hash_context), address_tag_hint.bytes);

// clean up cipher key bytes
memwipe(hash_context.cipher_key.bytes, 32);

return address_tag_hint;
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
jamtis_address_tag_cipher_context::jamtis_address_tag_cipher_context(const crypto::secret_key &cipher_key)
{
// cache the cipher key
m_cipher_key = cipher_key;

// prepare the Twofish key
Twofish_initialise();
Twofish_prepare_key(to_bytes(cipher_key), sizeof(rct::key), &(m_twofish_key));
Expand All @@ -141,7 +101,7 @@ jamtis_address_tag_cipher_context::~jamtis_address_tag_cipher_context()
//-------------------------------------------------------------------------------------------------------------------
address_tag_t jamtis_address_tag_cipher_context::cipher(const address_index_t &j) const
{
// address tag = cipher[k](j) || H_2(k, cipher[k](j))
// address tag = cipher[k](j)

// expect address index to fit in one Twofish block (16 bytes)
static_assert(sizeof(address_index_t) == TWOFISH_BLOCK_SIZE, "");
Expand All @@ -152,29 +112,20 @@ address_tag_t jamtis_address_tag_cipher_context::cipher(const address_index_t &j
// encrypt the address index
Twofish_encrypt_block(&m_twofish_key, encrypted_j.bytes, encrypted_j.bytes);

// make the address tag hint and complete the address tag
return make_address_tag(encrypted_j, get_address_tag_hint(m_cipher_key, encrypted_j));
// complete the address tag
return make_address_tag(encrypted_j);
}
//-------------------------------------------------------------------------------------------------------------------
bool jamtis_address_tag_cipher_context::try_decipher(const address_tag_t &addr_tag, address_index_t &j_out) const
void jamtis_address_tag_cipher_context::decipher(const address_tag_t &addr_tag, address_index_t &j_out) const
{
static_assert(sizeof(address_index_t) == TWOFISH_BLOCK_SIZE, "");
static_assert(sizeof(address_index_t) + sizeof(address_tag_hint_t) == sizeof(address_tag_t), "");
static_assert(sizeof(address_index_t) == sizeof(address_tag_t), "");

// extract the encrypted index
memcpy(j_out.bytes, addr_tag.bytes, sizeof(address_index_t));

// recover the address tag hint
const address_tag_hint_t address_tag_hint{get_address_tag_hint(m_cipher_key, j_out)};

// check the address tag hint
if (memcmp(addr_tag.bytes + sizeof(address_index_t), address_tag_hint.bytes, sizeof(address_tag_hint_t)) != 0)
return false;

// decrypt the address index
Twofish_decrypt_block(&m_twofish_key, j_out.bytes, j_out.bytes);

return true;
}
//-------------------------------------------------------------------------------------------------------------------
address_tag_t cipher_address_index(const jamtis_address_tag_cipher_context &cipher_context, const address_index_t &j)
Expand All @@ -191,22 +142,22 @@ address_tag_t cipher_address_index(const crypto::secret_key &cipher_key, const a
return cipher_address_index(cipher_context, j);
}
//-------------------------------------------------------------------------------------------------------------------
bool try_decipher_address_index(const jamtis_address_tag_cipher_context &cipher_context,
void decipher_address_index(const jamtis_address_tag_cipher_context &cipher_context,
const address_tag_t &addr_tag,
address_index_t &j_out)
{
return cipher_context.try_decipher(addr_tag, j_out);
cipher_context.decipher(addr_tag, j_out);
}
//-------------------------------------------------------------------------------------------------------------------
bool try_decipher_address_index(const crypto::secret_key &cipher_key,
void decipher_address_index(const crypto::secret_key &cipher_key,
const address_tag_t &addr_tag,
address_index_t &j_out)
{
// prepare to decipher the tag
const jamtis_address_tag_cipher_context cipher_context{cipher_key};

// decipher it
return try_decipher_address_index(cipher_context, addr_tag, j_out);
decipher_address_index(cipher_context, addr_tag, j_out);
}
//-------------------------------------------------------------------------------------------------------------------
encrypted_address_tag_t encrypt_address_tag(const rct::key &sender_receiver_secret,
Expand Down
Loading

0 comments on commit 537ba29

Please sign in to comment.