From d7f6d78c7a70bb44933d672d1bbacf9a172c2e8e Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Mon, 12 Aug 2024 11:15:23 +0200 Subject: [PATCH] review comments --- Cargo.lock | 89 ++++++++++--------- .../minotari_ledger_wallet/common/Cargo.toml | 1 + .../common/src/common_types.rs | 6 ++ .../minotari_ledger_wallet/common/src/lib.rs | 8 +- .../common/src/utils.rs | 72 +++++++++++++++ .../comms/examples/ledger_demo/main.rs | 8 +- .../comms/src/accessor_methods.rs | 24 +++-- .../minotari_ledger_wallet/comms/src/lib.rs | 34 ++++++- .../get_one_sided_metadata_signature.rs | 56 +++++++++--- .../minotari_ledger_wallet/wallet/src/main.rs | 1 + .../src/tari_address/dual_address.rs | 11 ++- .../src/transactions/key_manager/inner.rs | 5 +- .../src/transactions/key_manager/interface.rs | 7 +- .../src/transactions/key_manager/wrapper.rs | 5 +- .../wallet_output_builder.rs | 9 +- .../wallet/src/transaction_service/service.rs | 2 +- 16 files changed, 257 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47efb2424e..1f88263143 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,7 +197,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -208,7 +208,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -496,7 +496,7 @@ dependencies = [ "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", "syn_derive", ] @@ -851,7 +851,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -1286,7 +1286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -1364,7 +1364,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.38", + "syn 2.0.74", "synthez", ] @@ -1409,7 +1409,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -1622,7 +1622,7 @@ dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -1642,7 +1642,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -2099,7 +2099,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -2211,7 +2211,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.38", + "syn 2.0.74", "textwrap 0.16.0", "thiserror", "typed-builder", @@ -2847,7 +2847,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -3355,6 +3355,9 @@ dependencies = [ [[package]] name = "minotari_ledger_wallet_common" version = "1.1.0-pre.2" +dependencies = [ + "bs58 0.5.1", +] [[package]] name = "minotari_ledger_wallet_comms" @@ -3869,7 +3872,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -3988,7 +3991,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -4248,7 +4251,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -4393,7 +4396,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -4451,7 +4454,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -4644,9 +4647,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4770,9 +4773,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -5296,7 +5299,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -5363,9 +5366,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.190" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] @@ -5382,13 +5385,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -5410,7 +5413,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -5592,7 +5595,7 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -5816,9 +5819,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -5834,7 +5837,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -5861,7 +5864,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3d2c2202510a1e186e63e596d9318c91a8cbe85cd1a56a7be0c333e5f59ec8d" dependencies = [ - "syn 2.0.38", + "syn 2.0.74", "synthez-codegen", "synthez-core", ] @@ -5872,7 +5875,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f724aa6d44b7162f3158a57bccd871a77b39a4aef737e01bcdff41f4772c7746" dependencies = [ - "syn 2.0.38", + "syn 2.0.74", "synthez-core", ] @@ -5885,7 +5888,7 @@ dependencies = [ "proc-macro2", "quote", "sealed", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -6622,7 +6625,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -6767,7 +6770,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -7053,7 +7056,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -7189,7 +7192,7 @@ checksum = "29a3151c41d0b13e3d011f98adc24434560ef06673a155a6c7f66b9879eecce2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -7467,7 +7470,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", "wasm-bindgen-shared", ] @@ -7501,7 +7504,7 @@ checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7873,7 +7876,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] @@ -7893,7 +7896,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.74", ] [[package]] diff --git a/applications/minotari_ledger_wallet/common/Cargo.toml b/applications/minotari_ledger_wallet/common/Cargo.toml index 4855d177fc..c0584f20cd 100644 --- a/applications/minotari_ledger_wallet/common/Cargo.toml +++ b/applications/minotari_ledger_wallet/common/Cargo.toml @@ -6,3 +6,4 @@ license = "BSD-3-Clause" edition = "2021" [dependencies] +bs58 = { version = "0.5.1", default-features = false, features = ["alloc"] } \ No newline at end of file diff --git a/applications/minotari_ledger_wallet/common/src/common_types.rs b/applications/minotari_ledger_wallet/common/src/common_types.rs index be39cc81f7..1ea9114713 100644 --- a/applications/minotari_ledger_wallet/common/src/common_types.rs +++ b/applications/minotari_ledger_wallet/common/src/common_types.rs @@ -21,6 +21,7 @@ pub enum AppSW { KeyDeriveFromUniform = 0xB00A, RandomNonceFail = 0xB00B, BadBranchKey = 0xB00C, + MetadataSignatureFail = 0xB00D, WrongApduLength = 0x6e03, // See ledger-device-rust-sdk/ledger_device_sdk/src/io.rs:16 UserCancelled = 0x6e04, // See ledger-device-rust-sdk/ledger_device_sdk/src/io.rs:16 } @@ -42,6 +43,7 @@ impl TryFrom for AppSW { 0xB00A => Ok(AppSW::KeyDeriveFromUniform), 0xB00B => Ok(AppSW::RandomNonceFail), 0xB00C => Ok(AppSW::BadBranchKey), + 0xB00D => Ok(AppSW::MetadataSignatureFail), 0x6e03 => Ok(AppSW::WrongApduLength), 0x6e04 => Ok(AppSW::UserCancelled), _ => Err(String::from("Invalid value for AppSW (") + utils::u16_to_string(value).as_str() + ")"), @@ -148,6 +150,7 @@ mod test { (0xB00A, AppSW::KeyDeriveFromUniform), (0xB00B, AppSW::RandomNonceFail), (0xB00C, AppSW::BadBranchKey), + (0xB00D, AppSW::MetadataSignatureFail), (0x6e03, AppSW::WrongApduLength), (0x6e04, AppSW::UserCancelled), ]; @@ -190,6 +193,9 @@ mod test { AppSW::BadBranchKey => { assert_eq!(AppSW::try_from(*value).unwrap(), *expected_app_sw); }, + AppSW::MetadataSignatureFail => { + assert_eq!(AppSW::try_from(*value).unwrap(), *expected_app_sw); + }, AppSW::WrongApduLength => { assert_eq!(AppSW::try_from(*value).unwrap(), *expected_app_sw); }, diff --git a/applications/minotari_ledger_wallet/common/src/lib.rs b/applications/minotari_ledger_wallet/common/src/lib.rs index d0bc415354..a91df3f83f 100644 --- a/applications/minotari_ledger_wallet/common/src/lib.rs +++ b/applications/minotari_ledger_wallet/common/src/lib.rs @@ -10,4 +10,10 @@ extern crate alloc; pub mod common_types; mod utils; -pub use utils::{hex_to_bytes_serialized, PUSH_PUBKEY_IDENTIFIER}; +pub use utils::{ + get_public_spend_key_from_tari_dual_address, + hex_to_bytes_serialized, + tari_dual_address_display, + PUSH_PUBKEY_IDENTIFIER, + TARI_DUAL_ADDRESS_SIZE, +}; diff --git a/applications/minotari_ledger_wallet/common/src/utils.rs b/applications/minotari_ledger_wallet/common/src/utils.rs index de4ce31cd0..e6c2adf685 100644 --- a/applications/minotari_ledger_wallet/common/src/utils.rs +++ b/applications/minotari_ledger_wallet/common/src/utils.rs @@ -58,3 +58,75 @@ pub fn hex_to_bytes_serialized(identifier: &str, data: &str) -> Result, } Ok(serialized) } + +/// The Tari dual address size +pub const TARI_DUAL_ADDRESS_SIZE: usize = 67; + +/// Convert a serialized Tari dual address to a base58 string +pub fn tari_dual_address_display(address_bytes: &[u8; TARI_DUAL_ADDRESS_SIZE]) -> Result { + validate_checksum(address_bytes.as_ref())?; + let mut base58 = "".to_string(); + base58.push_str(&bs58::encode(&address_bytes[0..1]).into_string()); + base58.push_str(&bs58::encode(&address_bytes[1..2].to_vec()).into_string()); + base58.push_str(&bs58::encode(&address_bytes[2..]).into_string()); + Ok(base58) +} + +/// Get the public spend key bytes from a serialized Tari dual address +pub fn get_public_spend_key_from_tari_dual_address( + address_bytes: &[u8; TARI_DUAL_ADDRESS_SIZE], +) -> Result<[u8; 32], String> { + validate_checksum(address_bytes.as_ref())?; + let mut public_spend_key = [0u8; 32]; + public_spend_key.copy_from_slice(&address_bytes[34..66]); + Ok(public_spend_key) +} + +// Determine whether a byte slice ends with a valid checksum +// If it is valid, returns the underlying data slice (without the checksum) +fn validate_checksum(data: &[u8]) -> Result<&[u8], String> { + // Empty data is not allowed, nor data only consisting of a checksum + if data.len() < 2 { + return Err("ChecksumError::InputDataTooShort".to_string()); + } + + // It's sufficient to check the entire slice against a zero checksum + match compute_checksum(data) { + 0u8 => Ok(&data[..data.len() - 1]), + _ => Err("ChecksumError::InvalidChecksum".to_string()), + } +} + +// Compute the DammSum checksum for a byte slice +fn compute_checksum(data: &[u8]) -> u8 { + // Perform the Damm algorithm + let mask = mask(); + let mut result = 0u8; + + for digit in data { + result ^= *digit; // add + let overflow = (result & (1 << 7)) != 0; + result <<= 1; // double + if overflow { + // reduce + result ^= mask; + } + } + + result +} + +// Set up the mask, fixed for a dictionary size of `2^8 == 256` +// This can fail on invalid coefficients, which will cause a panic +// To ensure this doesn't happen in production, it is directly tested +fn mask() -> u8 { + const COEFFICIENTS: [u8; 3] = [4, 3, 1]; + let mut mask = 1u8; + + for bit in COEFFICIENTS { + let shift = 1u8.checked_shl(u32::from(bit)).unwrap(); + mask = mask.checked_add(shift).unwrap(); + } + + mask +} diff --git a/applications/minotari_ledger_wallet/comms/examples/ledger_demo/main.rs b/applications/minotari_ledger_wallet/comms/examples/ledger_demo/main.rs index 3a4ea20e25..612211ab18 100644 --- a/applications/minotari_ledger_wallet/comms/examples/ledger_demo/main.rs +++ b/applications/minotari_ledger_wallet/comms/examples/ledger_demo/main.rs @@ -39,6 +39,7 @@ use rand::{rngs::OsRng, RngCore}; use tari_common::configuration::Network; use tari_common_types::{ key_branches::TransactionKeyManagerBranch, + tari_address::TariAddress, types::{Commitment, PrivateKey, PublicKey}, }; use tari_crypto::{ @@ -295,8 +296,11 @@ fn main() { let sender_offset_key_index = OsRng.next_u64(); let mut metadata_signature_message_common = [0u8; 32]; OsRng.fill_bytes(&mut metadata_signature_message_common); - let receiver_public_spend_key = PublicKey::from_secret_key(&get_random_nonce()); let commitment_mask = get_random_nonce(); + let receiver_address = TariAddress::from_base58( + "f48ScXDKxTU3nCQsQrXHs4tnkAyLViSUpi21t7YuBNsJE1VpqFcNSeEzQWgNeCqnpRaCA9xRZ3VuV11F8pHyciegbCt", + ) + .unwrap(); match ledger_get_one_sided_metadata_signature( account, @@ -305,7 +309,7 @@ fn main() { 12345, sender_offset_key_index, &commitment_mask, - &receiver_public_spend_key, + &receiver_address, &metadata_signature_message_common, ) { Ok(signature) => println!( diff --git a/applications/minotari_ledger_wallet/comms/src/accessor_methods.rs b/applications/minotari_ledger_wallet/comms/src/accessor_methods.rs index f47a0389c5..c236e5b745 100644 --- a/applications/minotari_ledger_wallet/comms/src/accessor_methods.rs +++ b/applications/minotari_ledger_wallet/comms/src/accessor_methods.rs @@ -34,9 +34,14 @@ use rand::{rngs::OsRng, RngCore}; use tari_common::configuration::Network; use tari_common_types::{ key_branches::TransactionKeyManagerBranch, + tari_address::TariAddress, types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, Signature}, }; -use tari_crypto::dhke::DiffieHellmanSharedSecret; +use tari_crypto::{ + dhke::DiffieHellmanSharedSecret, + keys::{PublicKey as PK, SecretKey}, + ristretto::{RistrettoPublicKey, RistrettoSecretKey}, +}; use tari_script::{script, CheckSigSchnorrSignature}; use tari_utilities::{hex::Hex, ByteArray}; @@ -564,7 +569,7 @@ pub fn ledger_get_one_sided_metadata_signature( value: u64, sender_offset_key_index: u64, commitment_mask: &PrivateKey, - receiver_public_spend_key: &PublicKey, + receiver_address: &TariAddress, message: &[u8; 32], ) -> Result { debug!( @@ -575,13 +580,13 @@ pub fn ledger_get_one_sided_metadata_signature( verify_ledger_application()?; // Ensure that the serialized script produce expected results - let script = script!(PushPubKey(Box::new(receiver_public_spend_key.clone()))); + let test_key = RistrettoPublicKey::from_secret_key(&RistrettoSecretKey::random(&mut OsRng)); + let script = script!(PushPubKey(Box::new(test_key.clone()))); let mut serialized_script = Vec::new(); script .serialize(&mut serialized_script) .map_err(|e| LedgerDeviceError::Processing(e.to_string()))?; - let ledger_serialized_script = - hex_to_bytes_serialized(PUSH_PUBKEY_IDENTIFIER, &receiver_public_spend_key.to_hex())?; + let ledger_serialized_script = hex_to_bytes_serialized(PUSH_PUBKEY_IDENTIFIER, &test_key.to_hex())?; if serialized_script != ledger_serialized_script.clone() { return Err(LedgerDeviceError::Processing(format!( "PushPubKey script serialization mismatch: expected {:?}, got {:?}", @@ -589,13 +594,20 @@ pub fn ledger_get_one_sided_metadata_signature( ))); } + // Ensure the receiver address is valid + if let TariAddress::Single(_) = receiver_address { + return Err(LedgerDeviceError::Processing( + "Receiver address must be a Dual address".to_string(), + )); + } + let mut data = Vec::new(); data.extend_from_slice(&u64::from(network.as_byte()).to_le_bytes()); data.extend_from_slice(&u64::from(txo_version).to_le_bytes()); data.extend_from_slice(&sender_offset_key_index.to_le_bytes()); data.extend_from_slice(&value.to_le_bytes()); data.extend_from_slice(&commitment_mask.to_vec()); - data.extend_from_slice(&receiver_public_spend_key.to_vec()); + data.extend_from_slice(&receiver_address.to_vec()); data.extend_from_slice(&message.to_vec()); match Command::>::build_command(account, Instruction::GetOneSidedMetadataSignature, data).execute() { diff --git a/applications/minotari_ledger_wallet/comms/src/lib.rs b/applications/minotari_ledger_wallet/comms/src/lib.rs index a5c1bef4ce..da517546d5 100644 --- a/applications/minotari_ledger_wallet/comms/src/lib.rs +++ b/applications/minotari_ledger_wallet/comms/src/lib.rs @@ -27,8 +27,15 @@ pub mod ledger_wallet; #[cfg(test)] mod test { use borsh::BorshSerialize; - use minotari_ledger_wallet_common::{hex_to_bytes_serialized, PUSH_PUBKEY_IDENTIFIER}; + use minotari_ledger_wallet_common::{ + get_public_spend_key_from_tari_dual_address, + hex_to_bytes_serialized, + tari_dual_address_display, + PUSH_PUBKEY_IDENTIFIER, + TARI_DUAL_ADDRESS_SIZE, + }; use rand::rngs::OsRng; + use tari_common_types::tari_address::TariAddress; use tari_crypto::{ keys::{PublicKey, SecretKey}, ristretto::{RistrettoPublicKey, RistrettoSecretKey}, @@ -85,4 +92,29 @@ mod test { ); } } + + #[test] + // This is testing the destructuring of a 'TariAddress::DualAddress', and will highlight if any changes are made to + // the TariAddress serialization. + fn test_tari_dual_address_destructuring() { + let tari_address_base_58 = + "f48ScXDKxTU3nCQsQrXHs4tnkAyLViSUpi21t7YuBNsJE1VpqFcNSeEzQWgNeCqnpRaCA9xRZ3VuV11F8pHyciegbCt"; + let tari_address = TariAddress::from_base58(tari_address_base_58).unwrap(); + let tari_address_serialized = tari_address.to_vec(); + assert_eq!(TARI_DUAL_ADDRESS_SIZE, tari_address_serialized.len()); + let mut tari_address_bytes = [0u8; TARI_DUAL_ADDRESS_SIZE]; + tari_address_bytes.copy_from_slice(&tari_address_serialized); + // Displaying the address as a base58 string + assert_eq!( + tari_dual_address_display(&tari_address_bytes).unwrap(), + tari_address_base_58 + ); + // Getting the public spend key from the address + assert_eq!( + get_public_spend_key_from_tari_dual_address(&tari_address_bytes) + .unwrap() + .to_vec(), + tari_address.public_spend_key().to_vec() + ); + } } diff --git a/applications/minotari_ledger_wallet/wallet/src/handlers/get_one_sided_metadata_signature.rs b/applications/minotari_ledger_wallet/wallet/src/handlers/get_one_sided_metadata_signature.rs index 9fa6c13685..64af9a96be 100644 --- a/applications/minotari_ledger_wallet/wallet/src/handlers/get_one_sided_metadata_signature.rs +++ b/applications/minotari_ledger_wallet/wallet/src/handlers/get_one_sided_metadata_signature.rs @@ -14,9 +14,16 @@ use ledger_device_sdk::{ gadgets::{Field, MultiFieldReview, SingleMessage}, }, }; -use minotari_ledger_wallet_common::{hex_to_bytes_serialized, PUSH_PUBKEY_IDENTIFIER}; +use minotari_ledger_wallet_common::{ + get_public_spend_key_from_tari_dual_address, + hex_to_bytes_serialized, + tari_dual_address_display, + PUSH_PUBKEY_IDENTIFIER, + TARI_DUAL_ADDRESS_SIZE, +}; use tari_crypto::{ commitment::HomomorphicCommitmentFactory, + hashing::DomainSeparatedHasher, keys::PublicKey, ristretto::{ pedersen::{extended_commitment_factory::ExtendedPedersenCommitmentFactory, PedersenCommitment}, @@ -24,15 +31,15 @@ use tari_crypto::{ RistrettoPublicKey, RistrettoSecretKey, }, - tari_utilities::hex::Hex, + tari_utilities::{hex::Hex, ByteArray}, }; -use tari_hashing::TransactionHashDomain; +use tari_hashing::{KeyManagerTransactionsHashDomain, TransactionHashDomain}; use zeroize::Zeroizing; use crate::{ alloc::string::ToString, hashing::DomainSeparatedConsensusHasher, - utils::{derive_from_bip32_key, get_key_from_canonical_bytes}, + utils::{derive_from_bip32_key, get_key_from_canonical_bytes, get_key_from_uniform_bytes}, AppSW, KeyType, RESPONSE_VERSION, @@ -65,11 +72,19 @@ pub fn handler_get_one_sided_metadata_signature(comm: &mut Comm) -> Result<(), A let commitment_mask: Zeroizing = get_key_from_canonical_bytes::(&data[40..72])?.into(); - let receiver_public_spend_key: Zeroizing = - get_key_from_canonical_bytes::(&data[72..104])?.into(); + let mut receiver_address_bytes = [0u8; TARI_DUAL_ADDRESS_SIZE]; // 67 bytes + receiver_address_bytes.clone_from_slice(&data[72..139]); + + let receiver_address = match tari_dual_address_display(&receiver_address_bytes) { + Ok(address) => address, + Err(e) => { + SingleMessage::new(&format!("Error: {:?}", e.to_string())).show_and_wait(); + return Err(AppSW::MetadataSignatureFail); + }, + }; let mut metadata_signature_message_common = [0u8; 32]; - metadata_signature_message_common.clone_from_slice(&data[104..136]); + metadata_signature_message_common.clone_from_slice(&data[139..171]); let fields = [ Field { @@ -78,7 +93,7 @@ pub fn handler_get_one_sided_metadata_signature(comm: &mut Comm) -> Result<(), A }, Field { name: "Receiver", - value: &format!("{}", receiver_public_spend_key.to_hex()), + value: &format!("{}", receiver_address), }, ]; let review = MultiFieldReview::new( @@ -110,7 +125,16 @@ pub fn handler_get_one_sided_metadata_signature(comm: &mut Comm) -> Result<(), A let ephemeral_commitment = factory.commit(&r_x, &r_a); let ephemeral_pubkey = RistrettoPublicKey::from_secret_key(&ephemeral_private_key); - let script_message = message_from_script(network, &receiver_public_spend_key)?; + let receiver_public_spend_key: Zeroizing = + match get_public_spend_key_from_tari_dual_address(&receiver_address_bytes) { + Ok(bytes) => get_key_from_canonical_bytes::(&bytes)?.into(), + Err(e) => { + SingleMessage::new(&format!("Error: {:?}", e.to_string())).show_and_wait(); + return Err(AppSW::MetadataSignatureFail); + }, + }; + + let script_message = message_from_script(network, &commitment_mask, &receiver_public_spend_key)?; let metadata_signature_message = metadata_signature_message_from_script_and_common(network, &script_message, &metadata_signature_message_common); @@ -137,7 +161,7 @@ pub fn handler_get_one_sided_metadata_signature(comm: &mut Comm) -> Result<(), A Ok(sig) => sig, Err(e) => { SingleMessage::new(&format!("Signing error: {:?}", e.to_string())).show_and_wait(); - return Err(AppSW::ScriptSignatureFail); + return Err(AppSW::MetadataSignatureFail); }, }; @@ -179,13 +203,21 @@ fn metadata_signature_message_from_script_and_common(network: u64, script: &[u8; fn message_from_script( network: u64, + commitment_mask: &Zeroizing, receiver_public_spend_key: &Zeroizing, ) -> Result<[u8; 32], AppSW> { - let serialized_script = match hex_to_bytes_serialized(PUSH_PUBKEY_IDENTIFIER, &receiver_public_spend_key.to_hex()) { + let hasher = DomainSeparatedHasher::, KeyManagerTransactionsHashDomain>::new_with_label("script key"); + let hashed_bytes = hasher.chain(commitment_mask.as_bytes()).finalize(); + let hashed_commitment_mask = get_key_from_uniform_bytes(hashed_bytes.as_ref())?; + let hashed_commitment_mask_public_key = + Zeroizing::new(RistrettoPublicKey::from_secret_key(&hashed_commitment_mask)); + let stealth_key = Zeroizing::new(receiver_public_spend_key.deref() + hashed_commitment_mask_public_key.deref()); + + let serialized_script = match hex_to_bytes_serialized(PUSH_PUBKEY_IDENTIFIER, &stealth_key.deref().to_hex()) { Ok(script) => script, Err(e) => { SingleMessage::new(&format!("Script error: {:?}", e.to_string())).show_and_wait(); - return Err(AppSW::ScriptSignatureFail); + return Err(AppSW::MetadataSignatureFail); }, }; diff --git a/applications/minotari_ledger_wallet/wallet/src/main.rs b/applications/minotari_ledger_wallet/wallet/src/main.rs index 6fd13b6a7e..97c4e058d0 100644 --- a/applications/minotari_ledger_wallet/wallet/src/main.rs +++ b/applications/minotari_ledger_wallet/wallet/src/main.rs @@ -108,6 +108,7 @@ pub enum AppSW { KeyDeriveFromUniform = AppSWMapping::KeyDeriveFromUniform as u16, RandomNonceFail = AppSWMapping::RandomNonceFail as u16, BadBranchKey = AppSWMapping::BadBranchKey as u16, + MetadataSignatureFail = AppSWMapping::MetadataSignatureFail as u16, WrongApduLength = StatusWords::BadLen as u16, // See ledger-device-rust-sdk/ledger_device_sdk/src/io.rs:16 UserCancelled = StatusWords::UserCancelled as u16, // See ledger-device-rust-sdk/ledger_device_sdk/src/io.rs:16 } diff --git a/base_layer/common_types/src/tari_address/dual_address.rs b/base_layer/common_types/src/tari_address/dual_address.rs index 7f51610f93..d8f7aace39 100644 --- a/base_layer/common_types/src/tari_address/dual_address.rs +++ b/base_layer/common_types/src/tari_address/dual_address.rs @@ -188,12 +188,11 @@ impl DualAddress { /// Convert Tari Address to Base58 string pub fn to_base58(&self) -> String { let bytes = self.to_bytes(); - let mut network = bs58::encode(&bytes[0..1]).into_string(); - let features = bs58::encode(&bytes[1..2].to_vec()).into_string(); - let rest = bs58::encode(&bytes[2..]).into_string(); - network.push_str(&features); - network.push_str(&rest); - network + let mut base58 = "".to_string(); + base58.push_str(&bs58::encode(&bytes[0..1]).into_string()); + base58.push_str(&bs58::encode(&bytes[1..2].to_vec()).into_string()); + base58.push_str(&bs58::encode(&bytes[2..]).into_string()); + base58 } /// Convert Tari dual Address to hex diff --git a/base_layer/core/src/transactions/key_manager/inner.rs b/base_layer/core/src/transactions/key_manager/inner.rs index 3087c0a929..782b8738e8 100644 --- a/base_layer/core/src/transactions/key_manager/inner.rs +++ b/base_layer/core/src/transactions/key_manager/inner.rs @@ -41,6 +41,7 @@ use rand::RngCore; use strum::IntoEnumIterator; use tari_common_types::{ key_branches::TransactionKeyManagerBranch, + tari_address::TariAddress, types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, RangeProof, Signature}, wallet_types::WalletType, }; @@ -1382,7 +1383,7 @@ where TBackend: KeyManagerBackend + 'static metadata_signature_message_common: &[u8; 32], range_proof_type: RangeProofType, script: &TariScript, - receiver_public_spend_key: &PublicKey, + receiver_address: &TariAddress, ) -> Result { #[cfg(feature = "ledger")] { @@ -1441,7 +1442,7 @@ where TBackend: KeyManagerBackend + 'static value.into(), sender_offset_key_index, &commitment_mask, - receiver_public_spend_key, + receiver_address, metadata_signature_message_common, ) .map_err(TransactionError::LedgerDeviceError)?; diff --git a/base_layer/core/src/transactions/key_manager/interface.rs b/base_layer/core/src/transactions/key_manager/interface.rs index 8d021061cc..44a19cc555 100644 --- a/base_layer/core/src/transactions/key_manager/interface.rs +++ b/base_layer/core/src/transactions/key_manager/interface.rs @@ -25,7 +25,10 @@ use std::str::FromStr; use blake2::Blake2b; use digest::consts::U64; use strum_macros::EnumIter; -use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, RangeProof, Signature}; +use tari_common_types::{ + tari_address::TariAddress, + types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, RangeProof, Signature}, +}; use tari_comms::types::CommsDHKE; use tari_crypto::{hashing::DomainSeparatedHash, ristretto::RistrettoComSig}; use tari_key_manager::key_manager_service::{KeyAndId, KeyId, KeyManagerInterface, KeyManagerServiceError}; @@ -225,7 +228,7 @@ pub trait TransactionKeyManagerInterface: KeyManagerInterface { metadata_signature_message_common: &[u8; 32], range_proof_type: RangeProofType, script: &TariScript, - receiver_public_spend_key: &PublicKey, + receiver_address: &TariAddress, ) -> Result; async fn sign_script_message( diff --git a/base_layer/core/src/transactions/key_manager/wrapper.rs b/base_layer/core/src/transactions/key_manager/wrapper.rs index 80ac374a8e..260a3b341d 100644 --- a/base_layer/core/src/transactions/key_manager/wrapper.rs +++ b/base_layer/core/src/transactions/key_manager/wrapper.rs @@ -25,6 +25,7 @@ use std::sync::Arc; use blake2::Blake2b; use digest::consts::U64; use tari_common_types::{ + tari_address::TariAddress, types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, RangeProof, Signature}, wallet_types::WalletType, }; @@ -471,7 +472,7 @@ where TBackend: KeyManagerBackend + 'static metadata_signature_message_common: &[u8; 32], range_proof_type: RangeProofType, script: &TariScript, - receiver_public_spend_key: &PublicKey, + receiver_address: &TariAddress, ) -> Result { self.transaction_key_manager_inner .read() @@ -484,7 +485,7 @@ where TBackend: KeyManagerBackend + 'static metadata_signature_message_common, range_proof_type, script, - receiver_public_spend_key, + receiver_address, ) .await } diff --git a/base_layer/core/src/transactions/transaction_components/wallet_output_builder.rs b/base_layer/core/src/transactions/transaction_components/wallet_output_builder.rs index 33a85e901b..5a0622a2df 100644 --- a/base_layer/core/src/transactions/transaction_components/wallet_output_builder.rs +++ b/base_layer/core/src/transactions/transaction_components/wallet_output_builder.rs @@ -21,7 +21,10 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use derivative::Derivative; -use tari_common_types::types::{ComAndPubSignature, PublicKey}; +use tari_common_types::{ + tari_address::TariAddress, + types::{ComAndPubSignature, PublicKey}, +}; use tari_script::{ExecutionStack, TariScript}; use crate::{ @@ -204,7 +207,7 @@ impl WalletOutputBuilder { mut self, key_manager: &KM, sender_offset_key_id: &TariKeyId, - receiver_public_spend_key: &PublicKey, + receiver_address: &TariAddress, ) -> Result { let script = self .script @@ -227,7 +230,7 @@ impl WalletOutputBuilder { &metadata_message_common, self.features.range_proof_type, script, - receiver_public_spend_key, + receiver_address, ) .await?; self.metadata_signature = Some(metadata_signature); diff --git a/base_layer/wallet/src/transaction_service/service.rs b/base_layer/wallet/src/transaction_service/service.rs index de7c20d001..a61bc3cf13 100644 --- a/base_layer/wallet/src/transaction_service/service.rs +++ b/base_layer/wallet/src/transaction_service/service.rs @@ -1778,7 +1778,7 @@ where .sign_as_sender_and_receiver_verified( &self.resources.transaction_key_manager_service, &sender_offset_private_key, - dest_address.public_spend_key(), + &dest_address, ) .await? .try_build(&self.resources.transaction_key_manager_service)