Skip to content

Commit

Permalink
fix: stop reuse of nonce keys (#6464)
Browse files Browse the repository at this point in the history
Description
---
Stops the reuse of nonce keys when a wallet has been recovered.

Motivation and Context
---
Currently, nonce keys are based on incrementing key indexes. This is a
problem if the wallet is recovered as the wallet does not keep the index
of the nonce keys, but rather starts at 0 again. This change is to make
all nonce keys random u64.
  • Loading branch information
SWvheerden authored Aug 13, 2024
1 parent 574fa1e commit 131225c
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 70 deletions.
18 changes: 9 additions & 9 deletions base_layer/common_types/src/key_branches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ pub enum TransactionKeyManagerBranch {
PreMine = Branch::PreMine as u8,
}

const DATA_ENCRYPTION: &str = "data encryption";
const METADATA_EPHEMERAL_NONCE: &str = "metadata ephemeral nonce";
const COMMITMENT_MASK: &str = "commitment mask";
const NONCE: &str = "nonce";
const KERNEL_NONCE: &str = "kernel nonce";
const SENDER_OFFSET: &str = "sender offset";
const ONE_SIDED_SENDER_OFFSET: &str = "one sided sender offset";
const RANDOM_KEY: &str = "random key";
const PRE_MINE: &str = "pre-mine";
pub const DATA_ENCRYPTION: &str = "data encryption";
pub const METADATA_EPHEMERAL_NONCE: &str = "metadata ephemeral nonce";
pub const COMMITMENT_MASK: &str = "commitment mask";
pub const NONCE: &str = "nonce";
pub const KERNEL_NONCE: &str = "kernel nonce";
pub const SENDER_OFFSET: &str = "sender offset";
pub const ONE_SIDED_SENDER_OFFSET: &str = "one sided sender offset";
pub const RANDOM_KEY: &str = "random key";
pub const PRE_MINE: &str = "pre-mine";

impl TransactionKeyManagerBranch {
/// Warning: Changing these strings will affect the backwards compatibility of the wallet with older databases or
Expand Down
40 changes: 28 additions & 12 deletions base_layer/core/src/transactions/key_manager/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@ use minotari_ledger_wallet_comms::accessor_methods::{
ledger_get_script_signature,
ScriptSignatureKey,
};
use rand::rngs::OsRng;
#[cfg(feature = "ledger")]
use rand::RngCore;
use rand::{rngs::OsRng, RngCore};
use strum::IntoEnumIterator;
use tari_common_types::{
key_branches::TransactionKeyManagerBranch,
key_branches::{
TransactionKeyManagerBranch,
KERNEL_NONCE,
METADATA_EPHEMERAL_NONCE,
NONCE,
ONE_SIDED_SENDER_OFFSET,
RANDOM_KEY,
SENDER_OFFSET,
},
tari_address::TariAddress,
types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, RangeProof, Signature},
wallet_types::WalletType,
Expand Down Expand Up @@ -172,14 +178,24 @@ where TBackend: KeyManagerBackend<PublicKey> + 'static

pub async fn get_next_key(&self, branch: &str) -> Result<KeyAndId<PublicKey>, KeyManagerServiceError> {
let index = {
let mut km = self
.key_managers
.get(branch)
.ok_or_else(|| self.unknown_key_branch_error("get_next_key", branch))?
.write()
.await;
self.db.increment_key_index(branch)?;
km.increment_key_index(1)
match branch {
METADATA_EPHEMERAL_NONCE |
NONCE |
KERNEL_NONCE |
SENDER_OFFSET |
ONE_SIDED_SENDER_OFFSET |
RANDOM_KEY => OsRng.next_u64(),
_ => {
let mut km = self
.key_managers
.get(branch)
.ok_or_else(|| self.unknown_key_branch_error("get_next_key", branch))?
.write()
.await;
self.db.increment_key_index(branch)?;
km.increment_key_index(1)
},
}
};
let key_id = KeyId::Managed {
branch: branch.to_string(),
Expand Down
53 changes: 4 additions & 49 deletions base_layer/core/src/transactions/transaction_protocol/recipient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,25 +165,20 @@ impl ReceiverTransactionProtocol {

#[cfg(test)]
mod test {
use tari_common_types::{key_branches::TransactionKeyManagerBranch, types::PublicKey};
use tari_common_types::types::PublicKey;
use tari_crypto::keys::PublicKey as PublicKeyTrait;
use tari_key_manager::key_manager_service::{KeyId, KeyManagerInterface};
use tari_key_manager::key_manager_service::KeyManagerInterface;
use tari_script::TariScript;

use crate::{
covenants::Covenant,
test_helpers::create_consensus_constants,
transactions::{
crypto_factories::CryptoFactories,
key_manager::{create_memory_db_key_manager, TransactionKeyManagerInterface, TxoStage},
key_manager::{create_memory_db_key_manager, TransactionKeyManagerInterface},
tari_amount::*,
test_helpers::{TestParams, UtxoTestParams},
transaction_components::{
OutputFeatures,
TransactionKernel,
TransactionKernelVersion,
TransactionOutputVersion,
},
transaction_components::{OutputFeatures, TransactionKernelVersion, TransactionOutputVersion},
transaction_protocol::{
sender::{SingleRoundSenderData, TransactionSenderMessage},
TransactionMetadata,
Expand Down Expand Up @@ -246,46 +241,6 @@ mod test {
assert_eq!(&commitment, &data.output.commitment);
data.output.verify_range_proof(&factories.range_proof).unwrap();

let index = key_manager
.find_key_index(
TransactionKeyManagerBranch::KernelNonce.get_branch_key(),
data.partial_signature.get_public_nonce(),
)
.await
.unwrap();
let nonce_id = KeyId::Managed {
branch: TransactionKeyManagerBranch::KernelNonce.get_branch_key(),
index,
};
let kernel_message = TransactionKernel::build_kernel_signature_message(
&TransactionKernelVersion::get_current_version(),
m.fee,
m.lock_height,
&m.kernel_features,
&m.burn_commitment,
);
let p_nonce = key_manager.get_public_key_at_key_id(&nonce_id).await.unwrap();
let p_commitment_mask_key = key_manager
.get_txo_kernel_signature_excess_with_offset(&receiver_test_params.commitment_mask_key_id, &nonce_id)
.await
.unwrap();
let r_sum = &msg.public_nonce + &p_nonce;
let excess = &msg.public_excess + &p_commitment_mask_key;
let kernel_signature = key_manager
.get_partial_txo_kernel_signature(
&receiver_test_params.commitment_mask_key_id,
&nonce_id,
&r_sum,
&excess,
&TransactionKernelVersion::get_current_version(),
&kernel_message,
&m.kernel_features,
TxoStage::Output,
)
.await
.unwrap();
assert_eq!(data.partial_signature, kernel_signature);

let (mask, value, _) = key_manager.try_output_key_recovery(&data.output, None).await.unwrap();
assert_eq!(output.spending_key_id, mask);
assert_eq!(output.value, value);
Expand Down

0 comments on commit 131225c

Please sign in to comment.