diff --git a/Cargo.lock b/Cargo.lock index 05ef979dc0..aeb4c7d494 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5558,6 +5558,7 @@ version = "0.52.0-pre.1" dependencies = [ "anyhow", "bitflags 1.3.2", + "blake2", "chacha20 0.7.3", "chacha20poly1305 0.10.1", "chrono", @@ -5715,8 +5716,7 @@ dependencies = [ [[package]] name = "tari_crypto" version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc09581fc1a9709e54be25e0a50437dc405370b3f5795ee65dc913f4f7e726e5" +source = "git+https://github.com/AaronFeickert/tari-crypto?branch=scalar-byte-array#8dde0216b6ca305d52d703820481c55ebf7666ba" dependencies = [ "blake2", "borsh", @@ -5979,8 +5979,7 @@ dependencies = [ [[package]] name = "tari_utilities" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "367d17d09cf48e4cf45222fd48536e206f8ef3aaa5eed449c7df38d2ab4586c6" +source = "git+https://github.com/AaronFeickert/tari_utilities?branch=byte-array#e8598fc2734897ac36382fd943c087b84c99889f" dependencies = [ "base58-monero 0.3.2", "base64 0.13.1", diff --git a/Cargo.toml b/Cargo.toml index e9c531bbf9..d06a53889e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,3 +45,5 @@ overflow-checks = true [patch.crates-io] liblmdb-sys = { git = "https://github.com/tari-project/lmdb-rs", tag = "0.7.6-tari.1" } +tari_crypto = { git = "https://github.com/AaronFeickert/tari-crypto", branch = "scalar-byte-array" } # TODO: remove after merging +tari_utilities = { git = "https://github.com/AaronFeickert/tari_utilities", branch = "byte-array" } # TODO: remove after merging diff --git a/applications/minotari_app_grpc/src/conversions/block_header.rs b/applications/minotari_app_grpc/src/conversions/block_header.rs index 25beb80f40..ae7b479448 100644 --- a/applications/minotari_app_grpc/src/conversions/block_header.rs +++ b/applications/minotari_app_grpc/src/conversions/block_header.rs @@ -58,9 +58,11 @@ impl TryFrom for BlockHeader { type Error = String; fn try_from(header: grpc::BlockHeader) -> Result { - let total_kernel_offset = PrivateKey::from_bytes(&header.total_kernel_offset).map_err(|err| err.to_string())?; + let total_kernel_offset = + PrivateKey::from_canonical_bytes(&header.total_kernel_offset).map_err(|err| err.to_string())?; - let total_script_offset = PrivateKey::from_bytes(&header.total_script_offset).map_err(|err| err.to_string())?; + let total_script_offset = + PrivateKey::from_canonical_bytes(&header.total_script_offset).map_err(|err| err.to_string())?; let pow = match header.pow { Some(p) => ProofOfWork::try_from(p)?, diff --git a/applications/minotari_app_grpc/src/conversions/com_and_pub_signature.rs b/applications/minotari_app_grpc/src/conversions/com_and_pub_signature.rs index a26d1498da..24feb33063 100644 --- a/applications/minotari_app_grpc/src/conversions/com_and_pub_signature.rs +++ b/applications/minotari_app_grpc/src/conversions/com_and_pub_signature.rs @@ -31,13 +31,16 @@ impl TryFrom for ComAndPubSignature { type Error = String; fn try_from(sig: grpc::ComAndPubSignature) -> Result { - let ephemeral_commitment = Commitment::from_bytes(&sig.ephemeral_commitment) + let ephemeral_commitment = Commitment::from_canonical_bytes(&sig.ephemeral_commitment) .map_err(|_| "Could not get ephemeral commitment".to_string())?; - let ephemeral_pubkey = PublicKey::from_bytes(&sig.ephemeral_pubkey) + let ephemeral_pubkey = PublicKey::from_canonical_bytes(&sig.ephemeral_pubkey) .map_err(|_| "Could not get ephemeral public key".to_string())?; - let u_a = PrivateKey::from_bytes(&sig.u_a).map_err(|_| "Could not get partial signature u_a".to_string())?; - let u_x = PrivateKey::from_bytes(&sig.u_x).map_err(|_| "Could not get partial signature u_x".to_string())?; - let u_y = PrivateKey::from_bytes(&sig.u_y).map_err(|_| "Could not get partial signature u_y".to_string())?; + let u_a = PrivateKey::from_canonical_bytes(&sig.u_a) + .map_err(|_| "Could not get partial signature u_a".to_string())?; + let u_x = PrivateKey::from_canonical_bytes(&sig.u_x) + .map_err(|_| "Could not get partial signature u_x".to_string())?; + let u_y = PrivateKey::from_canonical_bytes(&sig.u_y) + .map_err(|_| "Could not get partial signature u_y".to_string())?; Ok(Self::new(ephemeral_commitment, ephemeral_pubkey, u_a, u_x, u_y)) } diff --git a/applications/minotari_app_grpc/src/conversions/commitment_signature.rs b/applications/minotari_app_grpc/src/conversions/commitment_signature.rs index be1734b8de..7bf61ff83e 100644 --- a/applications/minotari_app_grpc/src/conversions/commitment_signature.rs +++ b/applications/minotari_app_grpc/src/conversions/commitment_signature.rs @@ -32,10 +32,10 @@ impl TryFrom for CommitmentSignature Result { - let public_nonce = HomomorphicCommitment::::from_bytes(&sig.public_nonce) + let public_nonce = HomomorphicCommitment::::from_canonical_bytes(&sig.public_nonce) .map_err(|_| "Could not get public nonce".to_string())?; - let u = PrivateKey::from_bytes(&sig.u).map_err(|_| "Could not get u_x".to_string())?; - let v = PrivateKey::from_bytes(&sig.v).map_err(|_| "Could not get v_x".to_string())?; + let u = PrivateKey::from_canonical_bytes(&sig.u).map_err(|_| "Could not get u_x".to_string())?; + let v = PrivateKey::from_canonical_bytes(&sig.v).map_err(|_| "Could not get v_x".to_string())?; Ok(Self::new(public_nonce, u, v)) } diff --git a/applications/minotari_app_grpc/src/conversions/new_block_template.rs b/applications/minotari_app_grpc/src/conversions/new_block_template.rs index fee437949a..54c7ce94b2 100644 --- a/applications/minotari_app_grpc/src/conversions/new_block_template.rs +++ b/applications/minotari_app_grpc/src/conversions/new_block_template.rs @@ -76,9 +76,9 @@ impl TryFrom for NewBlockTemplate { fn try_from(block: grpc::NewBlockTemplate) -> Result { let header = block.header.clone().ok_or_else(|| "No header provided".to_string())?; - let total_kernel_offset = PrivateKey::from_bytes(&header.total_kernel_offset) + let total_kernel_offset = PrivateKey::from_canonical_bytes(&header.total_kernel_offset) .map_err(|err| format!("total_kernel_offset {}", err))?; - let total_script_offset = PrivateKey::from_bytes(&header.total_script_offset) + let total_script_offset = PrivateKey::from_canonical_bytes(&header.total_script_offset) .map_err(|err| format!("total_script_offset {}", err))?; let pow = match header.pow { Some(p) => ProofOfWork::try_from(p)?, diff --git a/applications/minotari_app_grpc/src/conversions/sidechain_feature.rs b/applications/minotari_app_grpc/src/conversions/sidechain_feature.rs index 90f5da2ad4..385b74faa3 100644 --- a/applications/minotari_app_grpc/src/conversions/sidechain_feature.rs +++ b/applications/minotari_app_grpc/src/conversions/sidechain_feature.rs @@ -88,7 +88,7 @@ impl TryFrom for ValidatorNodeRegistration { fn try_from(value: grpc::ValidatorNodeRegistration) -> Result { Ok(ValidatorNodeRegistration::new(ValidatorNodeSignature::new( - PublicKey::from_bytes(&value.public_key).map_err(|e| e.to_string())?, + PublicKey::from_canonical_bytes(&value.public_key).map_err(|e| e.to_string())?, value .signature .map(Signature::try_from) @@ -112,7 +112,7 @@ impl TryFrom for CodeTemplateRegistration { fn try_from(value: grpc::TemplateRegistration) -> Result { Ok(Self { - author_public_key: PublicKey::from_bytes(&value.author_public_key).map_err(|e| e.to_string())?, + author_public_key: PublicKey::from_canonical_bytes(&value.author_public_key).map_err(|e| e.to_string())?, author_signature: value .author_signature .map(Signature::try_from) @@ -157,7 +157,7 @@ impl TryFrom for ConfidentialOutputData { fn try_from(value: grpc::ConfidentialOutputData) -> Result { Ok(ConfidentialOutputData { - claim_public_key: PublicKey::from_bytes(&value.claim_public_key).map_err(|e| e.to_string())?, + claim_public_key: PublicKey::from_canonical_bytes(&value.claim_public_key).map_err(|e| e.to_string())?, }) } } diff --git a/applications/minotari_app_grpc/src/conversions/signature.rs b/applications/minotari_app_grpc/src/conversions/signature.rs index e00e881b60..c3e5e8c2c5 100644 --- a/applications/minotari_app_grpc/src/conversions/signature.rs +++ b/applications/minotari_app_grpc/src/conversions/signature.rs @@ -32,8 +32,9 @@ impl TryFrom for Signature { fn try_from(sig: grpc::Signature) -> Result { let public_nonce = - PublicKey::from_bytes(&sig.public_nonce).map_err(|_| "Could not get public nonce".to_string())?; - let signature = PrivateKey::from_bytes(&sig.signature).map_err(|_| "Could not get signature".to_string())?; + PublicKey::from_canonical_bytes(&sig.public_nonce).map_err(|_| "Could not get public nonce".to_string())?; + let signature = + PrivateKey::from_canonical_bytes(&sig.signature).map_err(|_| "Could not get signature".to_string())?; Ok(Self::new(public_nonce, signature)) } diff --git a/applications/minotari_app_grpc/src/conversions/transaction.rs b/applications/minotari_app_grpc/src/conversions/transaction.rs index 635d60658a..329e8ba570 100644 --- a/applications/minotari_app_grpc/src/conversions/transaction.rs +++ b/applications/minotari_app_grpc/src/conversions/transaction.rs @@ -64,12 +64,13 @@ impl TryFrom for Transaction { fn try_from(source: grpc::Transaction) -> Result { Ok(Self { - offset: RistrettoSecretKey::from_bytes(&source.offset).map_err(|e| format!("Offset is not valid:{}", e))?, + offset: RistrettoSecretKey::from_canonical_bytes(&source.offset) + .map_err(|e| format!("Offset is not valid:{}", e))?, body: source .body .ok_or_else(|| "Transaction body not provided".to_string())? .try_into()?, - script_offset: RistrettoSecretKey::from_bytes(&source.script_offset) + script_offset: RistrettoSecretKey::from_canonical_bytes(&source.script_offset) .map_err(|e| format!("Script offset is not valid:{}", e))?, }) } diff --git a/applications/minotari_app_grpc/src/conversions/transaction_input.rs b/applications/minotari_app_grpc/src/conversions/transaction_input.rs index 09d38988e7..ca45cbbcee 100644 --- a/applications/minotari_app_grpc/src/conversions/transaction_input.rs +++ b/applications/minotari_app_grpc/src/conversions/transaction_input.rs @@ -59,14 +59,14 @@ impl TryFrom for TransactionInput { script_signature, )) } else { - let commitment = Commitment::from_bytes(&input.commitment).map_err(|e| e.to_string())?; + let commitment = Commitment::from_canonical_bytes(&input.commitment).map_err(|e| e.to_string())?; let features = input .features .map(TryInto::try_into) .ok_or_else(|| "transaction output features not provided".to_string())??; - let sender_offset_public_key = - PublicKey::from_bytes(input.sender_offset_public_key.as_bytes()).map_err(|err| format!("{:?}", err))?; + let sender_offset_public_key = PublicKey::from_canonical_bytes(input.sender_offset_public_key.as_bytes()) + .map_err(|err| format!("{:?}", err))?; let encrypted_data = EncryptedData::from_bytes(&input.encrypted_data).map_err(|err| err.to_string())?; let minimum_value_promise = input.minimum_value_promise.into(); diff --git a/applications/minotari_app_grpc/src/conversions/transaction_kernel.rs b/applications/minotari_app_grpc/src/conversions/transaction_kernel.rs index 98af505948..174340f1b0 100644 --- a/applications/minotari_app_grpc/src/conversions/transaction_kernel.rs +++ b/applications/minotari_app_grpc/src/conversions/transaction_kernel.rs @@ -35,8 +35,8 @@ impl TryFrom for TransactionKernel { type Error = String; fn try_from(kernel: grpc::TransactionKernel) -> Result { - let excess = - Commitment::from_bytes(&kernel.excess).map_err(|err| format!("Excess could not be converted:{}", err))?; + let excess = Commitment::from_canonical_bytes(&kernel.excess) + .map_err(|err| format!("Excess could not be converted:{}", err))?; let excess_sig = kernel .excess_sig @@ -49,7 +49,7 @@ impl TryFrom for TransactionKernel { None } else { Some( - Commitment::from_bytes(&kernel.burn_commitment) + Commitment::from_canonical_bytes(&kernel.burn_commitment) .map_err(|err| format!("Burn commitment could not be converted:{}", err))?, ) }; diff --git a/applications/minotari_app_grpc/src/conversions/transaction_output.rs b/applications/minotari_app_grpc/src/conversions/transaction_output.rs index 9d5e45e0a1..88a0d9bb46 100644 --- a/applications/minotari_app_grpc/src/conversions/transaction_output.rs +++ b/applications/minotari_app_grpc/src/conversions/transaction_output.rs @@ -42,13 +42,13 @@ impl TryFrom for TransactionOutput { .map(TryInto::try_into) .ok_or_else(|| "Transaction output features not provided".to_string())??; - let commitment = - Commitment::from_bytes(&output.commitment).map_err(|err| format!("Invalid output commitment: {}", err))?; - let sender_offset_public_key = PublicKey::from_bytes(output.sender_offset_public_key.as_bytes()) + let commitment = Commitment::from_canonical_bytes(&output.commitment) + .map_err(|err| format!("Invalid output commitment: {}", err))?; + let sender_offset_public_key = PublicKey::from_canonical_bytes(output.sender_offset_public_key.as_bytes()) .map_err(|err| format!("Invalid sender_offset_public_key {:?}", err))?; let range_proof = if let Some(proof) = output.range_proof { - Some(BulletRangeProof::from_bytes(&proof.proof_bytes).map_err(|err| err.to_string())?) + Some(BulletRangeProof::from_canonical_bytes(&proof.proof_bytes).map_err(|err| err.to_string())?) } else { None }; diff --git a/applications/minotari_app_grpc/src/conversions/unblinded_output.rs b/applications/minotari_app_grpc/src/conversions/unblinded_output.rs index b65f875319..76a6f415cc 100644 --- a/applications/minotari_app_grpc/src/conversions/unblinded_output.rs +++ b/applications/minotari_app_grpc/src/conversions/unblinded_output.rs @@ -67,8 +67,8 @@ impl TryFrom for UnblindedOutput { type Error = String; fn try_from(mut output: grpc::UnblindedOutput) -> Result { - let spending_key = - PrivateKey::from_bytes(output.spending_key.as_bytes()).map_err(|e| format!("spending_key: {:?}", e))?; + let spending_key = PrivateKey::from_canonical_bytes(output.spending_key.as_bytes()) + .map_err(|e| format!("spending_key: {:?}", e))?; let features = output .features @@ -80,10 +80,10 @@ impl TryFrom for UnblindedOutput { let input_data = ExecutionStack::from_bytes(output.input_data.as_bytes()).map_err(|e| format!("input_data: {:?}", e))?; - let script_private_key = PrivateKey::from_bytes(output.script_private_key.as_bytes()) + let script_private_key = PrivateKey::from_canonical_bytes(output.script_private_key.as_bytes()) .map_err(|e| format!("script_private_key: {:?}", e))?; - let sender_offset_public_key = PublicKey::from_bytes(output.sender_offset_public_key.as_bytes()) + let sender_offset_public_key = PublicKey::from_canonical_bytes(output.sender_offset_public_key.as_bytes()) .map_err(|err| format!("sender_offset_public_key {:?}", err))?; let metadata_signature = output diff --git a/applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs b/applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs index e161327db4..ab6cb48ce8 100644 --- a/applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs +++ b/applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs @@ -604,7 +604,7 @@ impl wallet_server::Wallet for WalletGrpcServer { None } else { Some( - PublicKey::from_bytes(&message.claim_public_key) + PublicKey::from_canonical_bytes(&message.claim_public_key) .map_err(|e| Status::invalid_argument(e.to_string()))?, ) }, @@ -1005,7 +1005,7 @@ impl wallet_server::Wallet for WalletGrpcServer { ) -> Result, Status> { let request = request.into_inner(); let mut transaction_service = self.get_transaction_service(); - let validator_node_public_key = CommsPublicKey::from_bytes(&request.validator_node_public_key) + let validator_node_public_key = CommsPublicKey::from_canonical_bytes(&request.validator_node_public_key) .map_err(|_| Status::internal("Destination address is malformed".to_string()))?; let validator_node_signature = request .validator_node_signature diff --git a/applications/minotari_console_wallet/src/init/mod.rs b/applications/minotari_console_wallet/src/init/mod.rs index f42cc0f183..c047f16dc5 100644 --- a/applications/minotari_console_wallet/src/init/mod.rs +++ b/applications/minotari_console_wallet/src/init/mod.rs @@ -503,7 +503,7 @@ async fn detect_local_base_node(network: Network) -> Option { }; let resp = node_conn.identify(Empty {}).await.ok()?; let identity = resp.get_ref(); - let public_key = CommsPublicKey::from_bytes(&identity.public_key).ok()?; + let public_key = CommsPublicKey::from_canonical_bytes(&identity.public_key).ok()?; let addresses = identity .public_addresses .iter() diff --git a/applications/minotari_console_wallet/src/ui/state/tasks.rs b/applications/minotari_console_wallet/src/ui/state/tasks.rs index 75db08219c..6c9378a6e7 100644 --- a/applications/minotari_console_wallet/src/ui/state/tasks.rs +++ b/applications/minotari_console_wallet/src/ui/state/tasks.rs @@ -23,7 +23,7 @@ use std::{convert::TryFrom, path::PathBuf}; use blake2::Blake2b; -use digest::consts::U32; +use digest::consts::U64; use log::{error, warn}; use minotari_wallet::{ output_manager_service::UtxoSelectionCriteria, @@ -33,7 +33,7 @@ use minotari_wallet::{ use rand::{random, rngs::OsRng}; use tari_common_types::{ tari_address::TariAddress, - types::{FixedHash, PublicKey, Signature}, + types::{PublicKey, Signature}, }; use tari_core::{ consensus::{DomainSeparatedConsensusHasher, MaxSizeBytes, MaxSizeString}, @@ -421,7 +421,7 @@ pub async fn send_register_template_transaction_task( // signing and sending code template registration request // ---------------------------------------------------------------------------- - let mut km = KeyManager::>::new(); + let mut km = KeyManager::>::new(); let author_private_key = match km.next_key() { Ok(secret_key) => secret_key.key, @@ -434,16 +434,14 @@ pub async fn send_register_template_transaction_task( let author_public_key = PublicKey::from_secret_key(&author_private_key); let (secret_nonce, public_nonce) = PublicKey::random_keypair(&mut OsRng); - let challenge = FixedHash::from( - DomainSeparatedConsensusHasher::::new("template_registration") - .chain(&author_public_key) - .chain(&public_nonce) - .chain(&binary_sha) - .chain(&b"") - .finalize(), - ); - - let author_signature = Signature::sign_raw(&author_private_key, secret_nonce, &*challenge) + let challenge = DomainSeparatedConsensusHasher::>::new("template_registration") + .chain(&author_public_key) + .chain(&public_nonce) + .chain(&binary_sha) + .chain(&b"") + .finalize(); + + let author_signature = Signature::sign_raw_wide(&author_private_key, secret_nonce, &challenge) .expect("Sign cannot fail with 32-byte challenge and a RistrettoPublicKey"); // ---------------------------------------------------------------------------- diff --git a/applications/minotari_node/src/grpc/base_node_grpc_server.rs b/applications/minotari_node/src/grpc/base_node_grpc_server.rs index 1d130c9279..e6f4ed23d5 100644 --- a/applications/minotari_node/src/grpc/base_node_grpc_server.rs +++ b/applications/minotari_node/src/grpc/base_node_grpc_server.rs @@ -1004,7 +1004,7 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { let outputs = request .commitments .into_iter() - .map(|s| Commitment::from_bytes(&s)) + .map(|s| Commitment::from_canonical_bytes(&s)) .collect::, _>>() .map_err(|_| Status::invalid_argument("Invalid commitments provided"))?; @@ -1478,7 +1478,7 @@ impl tari_rpc::base_node_server::BaseNode for BaseNodeGrpcServer { let request = request.into_inner(); let report_error_flag = self.report_error_flag(); let mut handler = self.node_service.clone(); - let public_key = PublicKey::from_bytes(&request.public_key) + let public_key = PublicKey::from_canonical_bytes(&request.public_key) .map_err(|e| obscure_error_if_true(report_error_flag, Status::invalid_argument(e.to_string())))?; let shard_key = handler.get_shard_key(request.height, public_key).await.map_err(|e| { diff --git a/base_layer/common_types/src/emoji.rs b/base_layer/common_types/src/emoji.rs index 05cb0a870c..3d00a95f18 100644 --- a/base_layer/common_types/src/emoji.rs +++ b/base_layer/common_types/src/emoji.rs @@ -148,7 +148,7 @@ impl EmojiId { bytes.pop(); // Convert to a public key - match PublicKey::from_bytes(&bytes) { + match PublicKey::from_canonical_bytes(&bytes) { Ok(public_key) => Ok(Self(public_key)), Err(_) => Err(EmojiIdError::CannotRecoverPublicKey), } diff --git a/base_layer/common_types/src/tari_address.rs b/base_layer/common_types/src/tari_address.rs index 22c9b2bda2..b84403f9eb 100644 --- a/base_layer/common_types/src/tari_address.rs +++ b/base_layer/common_types/src/tari_address.rs @@ -134,7 +134,8 @@ impl TariAddress { if validate_checksum(&fixed_data).is_err() { return Err(TariAddressError::InvalidNetworkOrChecksum); } - let key = PublicKey::from_bytes(&bytes[0..32]).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; + let key = + PublicKey::from_canonical_bytes(&bytes[0..32]).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; Ok(TariAddress { public_key: key, network, @@ -151,7 +152,8 @@ impl TariAddress { // if the network is a valid network number, we can assume that the checksum as valid let network = Network::try_from(checksum ^ bytes[32]).map_err(|_| TariAddressError::InvalidNetworkOrChecksum)?; - let key = PublicKey::from_bytes(&bytes[0..32]).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; + let key = + PublicKey::from_canonical_bytes(&bytes[0..32]).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; Ok(TariAddress { public_key: key, network, diff --git a/base_layer/common_types/src/types/bullet_rangeproofs.rs b/base_layer/common_types/src/types/bullet_rangeproofs.rs index a00eb96b33..178e8dd6f7 100644 --- a/base_layer/common_types/src/types/bullet_rangeproofs.rs +++ b/base_layer/common_types/src/types/bullet_rangeproofs.rs @@ -59,7 +59,7 @@ impl ByteArray for BulletRangeProof { Ok(BulletRangeProof(v.clone())) } - fn from_bytes(bytes: &[u8]) -> Result { + fn from_canonical_bytes(bytes: &[u8]) -> Result { Ok(BulletRangeProof(bytes.to_vec())) } @@ -105,7 +105,7 @@ impl<'de> Deserialize<'de> for BulletRangeProof { fn visit_bytes(self, v: &[u8]) -> Result where E: de::Error { - BulletRangeProof::from_bytes(v).map_err(E::custom) + BulletRangeProof::from_canonical_bytes(v).map_err(E::custom) } } diff --git a/base_layer/common_types/src/types/mod.rs b/base_layer/common_types/src/types/mod.rs index b42fe9d50c..5c2f7cdfd2 100644 --- a/base_layer/common_types/src/types/mod.rs +++ b/base_layer/common_types/src/types/mod.rs @@ -25,7 +25,7 @@ mod fixed_hash; use blake2::Blake2b; pub use bullet_rangeproofs::BulletRangeProof; -use digest::consts::U32; +use digest::consts::{U32, U64}; use tari_crypto::{ hasher, ristretto::{ @@ -62,10 +62,10 @@ pub type PublicKey = RistrettoPublicKey; pub type PrivateKey = RistrettoSecretKey; /// Define the hash function that will be used to produce a signature challenge -pub type SignatureHasher = Blake2b; +pub type SignatureHasher = Blake2b; /// Specify the digest type for signature challenges -pub type Challenge = Blake2b; +pub type Challenge = Blake2b; /// Define the data type that is used to store results of a hash output pub type HashOutput = FixedHash; @@ -82,7 +82,7 @@ pub type RangeProof = BulletRangeProof; use tari_crypto::{hash_domain, hashing::DomainSeparatedHasher}; hasher!( - Blake2b, + Blake2b, WalletHasher, "com.tari.base_layer.wallet", 1, diff --git a/base_layer/core/src/base_node/proto/request.rs b/base_layer/core/src/base_node/proto/request.rs index 09a2c95d10..189ce82ab8 100644 --- a/base_layer/core/src/base_node/proto/request.rs +++ b/base_layer/core/src/base_node/proto/request.rs @@ -44,7 +44,9 @@ impl TryInto for ProtoNodeCommsRequest { let excess_sigs = excess_sigs .excess_sigs .into_iter() - .map(|bytes| PrivateKey::from_bytes(&bytes).map_err(|_| "Malformed excess sig".to_string())) + .map(|bytes| { + PrivateKey::from_canonical_bytes(&bytes).map_err(|_| "Malformed excess sig".to_string()) + }) .collect::>()?; NodeCommsRequest::FetchMempoolTransactionsByExcessSigs { excess_sigs } diff --git a/base_layer/core/src/base_node/proto/response.rs b/base_layer/core/src/base_node/proto/response.rs index 258bbf8f56..182c8c4653 100644 --- a/base_layer/core/src/base_node/proto/response.rs +++ b/base_layer/core/src/base_node/proto/response.rs @@ -56,7 +56,9 @@ impl TryInto for ProtoNodeCommsResponse { let not_found = response .not_found .into_iter() - .map(|bytes| PrivateKey::from_bytes(&bytes).map_err(|_| "Malformed excess signature".to_string())) + .map(|bytes| { + PrivateKey::from_canonical_bytes(&bytes).map_err(|_| "Malformed excess signature".to_string()) + }) .collect::>()?; NodeCommsResponse::FetchMempoolTransactionsByExcessSigsResponse( self::FetchMempoolTransactionsResponse { diff --git a/base_layer/core/src/blocks/block_header.rs b/base_layer/core/src/blocks/block_header.rs index eda64c7728..ce45fa2d41 100644 --- a/base_layer/core/src/blocks/block_header.rs +++ b/base_layer/core/src/blocks/block_header.rs @@ -43,8 +43,10 @@ use std::{ fmt::{Display, Error, Formatter}, }; +use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; use chrono::{DateTime, NaiveDateTime, Utc}; +use digest::consts::U32; use serde::{Deserialize, Serialize}; use tari_common_types::types::{BlockHash, FixedHash, PrivateKey}; use tari_utilities::{epoch_time::EpochTime, hex::Hex}; @@ -139,7 +141,7 @@ impl BlockHeader { } pub fn hash(&self) -> FixedHash { - DomainSeparatedConsensusHasher::::new("block_header") + DomainSeparatedConsensusHasher::>::new("block_header") .chain(&self.mining_hash()) .chain(&self.pow) .chain(&self.nonce) @@ -216,7 +218,7 @@ impl BlockHeader { /// Provides a mining hash of the header, used for the mining. /// This differs from the normal hash by not hashing the nonce and kernel pow. pub fn mining_hash(&self) -> FixedHash { - DomainSeparatedConsensusHasher::::new("block_header") + DomainSeparatedConsensusHasher::>::new("block_header") .chain(&self.version) .chain(&self.height) .chain(&self.prev_hash) diff --git a/base_layer/core/src/chain_storage/blockchain_database.rs b/base_layer/core/src/chain_storage/blockchain_database.rs index 4e8547d4e9..a3b7942364 100644 --- a/base_layer/core/src/chain_storage/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/blockchain_database.rs @@ -31,7 +31,9 @@ use std::{ time::Instant, }; +use blake2::Blake2b; use croaring::Bitmap; +use digest::consts::U32; use log::*; use serde::{Deserialize, Serialize}; use tari_common_types::{ @@ -1392,7 +1394,7 @@ pub fn calculate_mmr_roots( pub fn calculate_validator_node_mr(validator_nodes: &[(PublicKey, [u8; 32])]) -> tari_mmr::Hash { fn hash_node((pk, s): &(PublicKey, [u8; 32])) -> Vec { - DomainSeparatedConsensusHasher::::new("validator_node") + DomainSeparatedConsensusHasher::>::new("validator_node") .chain(pk) .chain(s) .finalize() diff --git a/base_layer/core/src/common/mod.rs b/base_layer/core/src/common/mod.rs index b9a2d30dc2..88eeda8288 100644 --- a/base_layer/core/src/common/mod.rs +++ b/base_layer/core/src/common/mod.rs @@ -23,6 +23,8 @@ #[cfg(feature = "base_node")] use std::time::Duration; +use blake2::Blake2b; +use digest::consts::U64; use tari_crypto::hash_domain; use crate::consensus::DomainSeparatedConsensusHasher; @@ -38,7 +40,7 @@ pub mod rolling_vec; hash_domain!(ConfidentialOutputHashDomain, "com.tari.dan.confidential_output", 1); /// Hasher used in the DAN to derive masks and encrypted value keys -pub type ConfidentialOutputHasher = DomainSeparatedConsensusHasher; +pub type ConfidentialOutputHasher = DomainSeparatedConsensusHasher>; /// The reason for a peer being banned #[cfg(feature = "base_node")] diff --git a/base_layer/core/src/common/one_sided.rs b/base_layer/core/src/common/one_sided.rs index 645c234ba8..c721bf933d 100644 --- a/base_layer/core/src/common/one_sided.rs +++ b/base_layer/core/src/common/one_sided.rs @@ -23,15 +23,15 @@ use core::result::Result; use blake2::Blake2b; -use digest::consts::U32; +use digest::consts::U64; use tari_common_types::types::{PrivateKey, PublicKey, WalletHasher}; use tari_comms::types::CommsDHKE; use tari_crypto::{ hash_domain, hashing::{DomainSeparatedHash, DomainSeparatedHasher}, - keys::PublicKey as PKtrait, + keys::{PublicKey as PKtrait, SecretKey as SKtrait}, }; -use tari_utilities::{byte_array::ByteArrayError, ByteArray}; +use tari_utilities::byte_array::ByteArrayError; hash_domain!( WalletOutputRewindKeysDomain, @@ -51,12 +51,12 @@ hash_domain!( 1 ); -type WalletOutputEncryptionKeysDomainHasher = DomainSeparatedHasher, WalletOutputEncryptionKeysDomain>; -type WalletOutputSpendingKeysDomainHasher = DomainSeparatedHasher, WalletOutputSpendingKeysDomain>; +type WalletOutputEncryptionKeysDomainHasher = DomainSeparatedHasher, WalletOutputEncryptionKeysDomain>; +type WalletOutputSpendingKeysDomainHasher = DomainSeparatedHasher, WalletOutputSpendingKeysDomain>; /// Generate an output encryption key from a Diffie-Hellman shared secret pub fn shared_secret_to_output_encryption_key(shared_secret: &CommsDHKE) -> Result { - PrivateKey::from_bytes( + PrivateKey::from_bytes_wide( WalletOutputEncryptionKeysDomainHasher::new() .chain(shared_secret.as_bytes()) .finalize() @@ -66,7 +66,7 @@ pub fn shared_secret_to_output_encryption_key(shared_secret: &CommsDHKE) -> Resu /// Generate an output spending key from a Diffie-Hellman shared secret pub fn shared_secret_to_output_spending_key(shared_secret: &CommsDHKE) -> Result { - PrivateKey::from_bytes( + PrivateKey::from_bytes_wide( WalletOutputSpendingKeysDomainHasher::new() .chain(shared_secret.as_bytes()) .finalize() @@ -78,7 +78,7 @@ pub fn shared_secret_to_output_spending_key(shared_secret: &CommsDHKE) -> Result pub fn diffie_hellman_stealth_domain_hasher( private_key: &PrivateKey, public_key: &PublicKey, -) -> DomainSeparatedHash> { +) -> DomainSeparatedHash> { WalletHasher::new_with_label("stealth_address") .chain(CommsDHKE::new(private_key, public_key).as_bytes()) .finalize() @@ -86,11 +86,11 @@ pub fn diffie_hellman_stealth_domain_hasher( /// Stealth payment script spending key pub fn stealth_address_script_spending_key( - dh_domain_hasher: &DomainSeparatedHash>, + dh_domain_hasher: &DomainSeparatedHash>, destination_public_key: &PublicKey, ) -> PublicKey { PublicKey::from_secret_key( - &PrivateKey::from_bytes(dh_domain_hasher.as_ref()) - .expect("'DomainSeparatedHash>' has correct size"), + &PrivateKey::from_bytes_wide(dh_domain_hasher.as_ref()) + .expect("'DomainSeparatedHash>' has correct size"), ) + destination_public_key } diff --git a/base_layer/core/src/consensus/consensus_encoding/hashing.rs b/base_layer/core/src/consensus/consensus_encoding/hashing.rs index feb5b4af66..8c66d25b67 100644 --- a/base_layer/core/src/consensus/consensus_encoding/hashing.rs +++ b/base_layer/core/src/consensus/consensus_encoding/hashing.rs @@ -24,16 +24,24 @@ use std::{io, io::Write, marker::PhantomData}; use blake2::Blake2b; use borsh::BorshSerialize; -use digest::{consts::U32, Digest}; +use digest::{ + consts::{U32, U64}, + Digest, +}; use tari_crypto::{hash_domain, hashing::DomainSeparation}; /// Domain separated consensus encoding hasher. -pub struct DomainSeparatedConsensusHasher(PhantomData); +pub struct DomainSeparatedConsensusHasher { + _m: PhantomData, + _d: PhantomData, +} -impl DomainSeparatedConsensusHasher { +impl DomainSeparatedConsensusHasher +where D: Default +{ #[allow(clippy::new_ret_no_self)] - pub fn new(label: &'static str) -> ConsensusHasher> { - let mut digest = Blake2b::::default(); + pub fn new(label: &'static str) -> ConsensusHasher { + let mut digest = D::default(); M::add_domain_separation_tag(&mut digest, label); ConsensusHasher::from_digest(digest) } @@ -52,9 +60,7 @@ impl ConsensusHasher { } } -impl ConsensusHasher -where D: Digest -{ +impl ConsensusHasher> { pub fn finalize(self) -> [u8; 32] { self.writer.0.finalize().into() } @@ -70,6 +76,22 @@ where D: Digest } } +impl ConsensusHasher> { + pub fn finalize(self) -> [u8; 64] { + self.writer.0.finalize().into() + } + + pub fn update_consensus_encode(&mut self, data: &T) { + BorshSerialize::serialize(data, &mut self.writer) + .expect("Incorrect implementation of BorshSerialize encountered. Implementations MUST be infallible."); + } + + pub fn chain(mut self, data: &T) -> Self { + self.update_consensus_encode(data); + self + } +} + impl Default for ConsensusHasher> { /// This `default` implementation is provided for convenience, but should not be used as the de-facto consensus /// hasher, rather create a new unique hash domain. @@ -79,7 +101,20 @@ impl Default for ConsensusHasher> { "com.tari.base_layer.core.consensus.consensus_encoding.hashing", 0 ); - DomainSeparatedConsensusHasher::::new("default") + DomainSeparatedConsensusHasher::>::new("default") + } +} + +impl Default for ConsensusHasher> { + /// This `default` implementation is provided for convenience, but should not be used as the de-facto consensus + /// hasher, rather create a new unique hash domain. + fn default() -> Self { + hash_domain!( + DefaultConsensusHashDomain, + "com.tari.base_layer.core.consensus.consensus_encoding.hashing", + 0 + ); + DomainSeparatedConsensusHasher::>::new("default") } } @@ -116,7 +151,7 @@ mod tests { TestHashDomain::add_domain_separation_tag(&mut hasher, "foo"); let expected_hash = hasher.chain_update(b"\xff\x00\x00\x00\x00\x00\x00\x00").finalize(); - let hash = DomainSeparatedConsensusHasher::::new("foo") + let hash = DomainSeparatedConsensusHasher::>::new("foo") .chain(&255u64) .finalize(); @@ -131,7 +166,7 @@ mod tests { TestHashDomain::add_domain_separation_tag(&mut hasher, "foo"); let expected_hash = hasher.chain_update(b"\x01\x73").finalize(); - let hash = DomainSeparatedConsensusHasher::::new("foo") + let hash = DomainSeparatedConsensusHasher::>::new("foo") .chain(&test_subject) .finalize(); @@ -139,13 +174,13 @@ mod tests { } #[test] - fn default_consensus_hash_is_not_blake256_default_hash() { - let blake256_hasher = Blake2b::::default(); - let blake256_hash = blake256_hasher.chain_update(b"").finalize(); + fn default_consensus_hash_is_not_blake_default_hash() { + let blake_hasher = Blake2b::::default(); + let blake_hash = blake_hasher.chain_update(b"").finalize(); - let default_consensus_hasher = ConsensusHasher::default(); + let default_consensus_hasher = ConsensusHasher::>::default(); let default_consensus_hash = default_consensus_hasher.chain(b"").finalize(); - assert_ne!(blake256_hash.as_slice(), default_consensus_hash.as_slice()); + assert_ne!(blake_hash.as_slice(), default_consensus_hash.as_slice()); } } diff --git a/base_layer/core/src/covenants/filters/fields_hashed_eq.rs b/base_layer/core/src/covenants/filters/fields_hashed_eq.rs index 8e278aa5ba..fe26c56453 100644 --- a/base_layer/core/src/covenants/filters/fields_hashed_eq.rs +++ b/base_layer/core/src/covenants/filters/fields_hashed_eq.rs @@ -44,9 +44,9 @@ impl Filter for FieldsHashedEqFilter { #[cfg(test)] mod test { + use blake2::Blake2b; use borsh::BorshSerialize; - use digest::Update; - use tari_common_types::types::Challenge; + use digest::{consts::U32, Update}; use tari_crypto::hashing::DomainSeparation; use super::*; @@ -72,7 +72,7 @@ mod test { sidechain_feature: Some(make_sample_sidechain_feature()), ..Default::default() }; - let mut hasher = Challenge::new(); + let mut hasher = Blake2b::::new(); BaseLayerCovenantsDomain::add_domain_separation_tag(&mut hasher, COVENANTS_FIELD_HASHER_LABEL); let hash = hasher.chain(features.try_to_vec().unwrap()).finalize(); let covenant = covenant!(fields_hashed_eq(@fields(@field::features), @hash(hash.into()))); diff --git a/base_layer/core/src/proof_of_work/monero_rx/fixed_array.rs b/base_layer/core/src/proof_of_work/monero_rx/fixed_array.rs index 1d9482872f..18ee2e4738 100644 --- a/base_layer/core/src/proof_of_work/monero_rx/fixed_array.rs +++ b/base_layer/core/src/proof_of_work/monero_rx/fixed_array.rs @@ -60,7 +60,7 @@ impl BorshDeserialize for FixedByteArray { bytes.push(u8::deserialize_reader(reader)?); } // This unwrap should never fail, the len is checked above. - Ok(Self::from_bytes(bytes.as_bytes()).unwrap()) + Ok(Self::from_canonical_bytes(bytes.as_bytes()).unwrap()) } } @@ -113,7 +113,7 @@ impl Default for FixedByteArray { } impl ByteArray for FixedByteArray { - fn from_bytes(bytes: &[u8]) -> Result { + fn from_canonical_bytes(bytes: &[u8]) -> Result { if bytes.len() > MAX_ARR_SIZE { return Err(ByteArrayError::IncorrectLength {}); } @@ -141,9 +141,9 @@ mod test { #[test] fn from_bytes() { - let empty = FixedByteArray::from_bytes(&[]).unwrap(); + let empty = FixedByteArray::from_canonical_bytes(&[]).unwrap(); assert_eq!(empty.len(), 0); - let arr = FixedByteArray::from_bytes(&[1u8][..]).unwrap(); + let arr = FixedByteArray::from_canonical_bytes(&[1u8][..]).unwrap(); assert_eq!(arr.len(), 1); assert!(arr.iter().all(|b| *b == 1)); // Iterates only up to len @@ -154,11 +154,11 @@ mod test { } assert!(used); - let arr = FixedByteArray::from_bytes(&[1u8; 63][..]).unwrap(); + let arr = FixedByteArray::from_canonical_bytes(&[1u8; 63][..]).unwrap(); assert_eq!(arr.len(), 63); assert!(arr.iter().all(|b| *b == 1)); - FixedByteArray::from_bytes(&[1u8; 64][..]).unwrap_err(); + FixedByteArray::from_canonical_bytes(&[1u8; 64][..]).unwrap_err(); } #[test] @@ -178,7 +178,7 @@ mod test { #[test] fn test_borsh_de_serialization() { - let fixed_byte_array = FixedByteArray::from_bytes(&[5, 6, 7]).unwrap(); + let fixed_byte_array = FixedByteArray::from_canonical_bytes(&[5, 6, 7]).unwrap(); let mut buf = Vec::new(); fixed_byte_array.serialize(&mut buf).unwrap(); buf.extend_from_slice(&[1, 2, 3]); diff --git a/base_layer/core/src/proof_of_work/monero_rx/helpers.rs b/base_layer/core/src/proof_of_work/monero_rx/helpers.rs index a79ae6604f..663fb69cea 100644 --- a/base_layer/core/src/proof_of_work/monero_rx/helpers.rs +++ b/base_layer/core/src/proof_of_work/monero_rx/helpers.rs @@ -345,7 +345,7 @@ mod test { let monero_data = MoneroPowData { header: block.header, - randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), transaction_count: u16::try_from(hashes.len()).unwrap(), merkle_root: root, coinbase_merkle_proof, @@ -406,7 +406,7 @@ mod test { let coinbase_merkle_proof = create_merkle_proof(&hashes).unwrap(); let monero_data = MoneroPowData { header: block.header, - randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), transaction_count: count, merkle_root: root, coinbase_merkle_proof, @@ -454,7 +454,7 @@ mod test { let coinbase_merkle_proof = create_merkle_proof(&hashes).unwrap(); let monero_data = MoneroPowData { header: block.header, - randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), transaction_count: count, merkle_root: root, coinbase_merkle_proof, @@ -510,7 +510,7 @@ mod test { let coinbase_merkle_proof = create_merkle_proof(&hashes).unwrap(); let monero_data = MoneroPowData { header: block.header, - randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), transaction_count: count, merkle_root: root, coinbase_merkle_proof, @@ -569,7 +569,7 @@ mod test { let coinbase_merkle_proof = create_merkle_proof(&hashes).unwrap(); let monero_data = MoneroPowData { header: block.header, - randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), transaction_count: count, merkle_root: root, coinbase_merkle_proof, @@ -624,7 +624,7 @@ mod test { let coinbase_merkle_proof = create_merkle_proof(&hashes).unwrap(); let monero_data = MoneroPowData { header: block.header, - randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), transaction_count: count, merkle_root: root, coinbase_merkle_proof, @@ -717,7 +717,7 @@ mod test { let coinbase_merkle_proof = create_merkle_proof(&hashes).unwrap(); let monero_data = MoneroPowData { header: block.header, - randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&from_hex(&seed_hash).unwrap()).unwrap(), transaction_count: count, merkle_root: Hash::null(), coinbase_merkle_proof, diff --git a/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs b/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs index e5cd075903..35b0473c6a 100644 --- a/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs +++ b/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs @@ -168,7 +168,7 @@ mod test { prev_id: Hash::new([4; 32]), nonce: 5, }, - randomx_key: FixedByteArray::from_bytes(&[6, 7, 8]).unwrap(), + randomx_key: FixedByteArray::from_canonical_bytes(&[6, 7, 8]).unwrap(), transaction_count: 9, merkle_root: Hash::new([10; 32]), coinbase_merkle_proof: MerkleProof::default(), diff --git a/base_layer/core/src/proto/block.rs b/base_layer/core/src/proto/block.rs index 256f23f279..37c334c76b 100644 --- a/base_layer/core/src/proto/block.rs +++ b/base_layer/core/src/proto/block.rs @@ -141,7 +141,7 @@ impl TryFrom for BlockHeaderAccumulatedData { accumulated_sha3x_difficulty: Difficulty::from_u64(source.accumulated_sha3x_difficulty) .map_err(|e| e.to_string())?, target_difficulty: Difficulty::from_u64(source.target_difficulty).map_err(|e| e.to_string())?, - total_kernel_offset: PrivateKey::from_bytes(source.total_kernel_offset.as_slice()) + total_kernel_offset: PrivateKey::from_canonical_bytes(source.total_kernel_offset.as_slice()) .map_err(|err| format!("Invalid value for total_kernel_offset: {}", err))?, }) } @@ -166,7 +166,7 @@ impl TryFrom for NewBlock { kernel_excess_sigs: new_block .kernel_excess_sigs .iter() - .map(|bytes| PrivateKey::from_bytes(bytes)) + .map(|bytes| PrivateKey::from_canonical_bytes(bytes)) .collect::, _>>() .map_err(|_| "Invalid excess signature scalar")?, }) diff --git a/base_layer/core/src/proto/block_header.rs b/base_layer/core/src/proto/block_header.rs index 05cb5ecea1..2fc1d47d58 100644 --- a/base_layer/core/src/proto/block_header.rs +++ b/base_layer/core/src/proto/block_header.rs @@ -37,9 +37,11 @@ impl TryFrom for BlockHeader { type Error = String; fn try_from(header: proto::BlockHeader) -> Result { - let total_kernel_offset = PrivateKey::from_bytes(&header.total_kernel_offset).map_err(|err| err.to_string())?; + let total_kernel_offset = + PrivateKey::from_canonical_bytes(&header.total_kernel_offset).map_err(|err| err.to_string())?; - let total_script_offset = PrivateKey::from_bytes(&header.total_script_offset).map_err(|err| err.to_string())?; + let total_script_offset = + PrivateKey::from_canonical_bytes(&header.total_script_offset).map_err(|err| err.to_string())?; let pow = match header.pow { Some(p) => ProofOfWork::try_from(p)?, diff --git a/base_layer/core/src/proto/sidechain_feature.rs b/base_layer/core/src/proto/sidechain_feature.rs index 4430148947..fbc29c98c1 100644 --- a/base_layer/core/src/proto/sidechain_feature.rs +++ b/base_layer/core/src/proto/sidechain_feature.rs @@ -90,7 +90,7 @@ impl TryFrom for ValidatorNodeRegistrat fn try_from(value: proto::types::ValidatorNodeRegistration) -> Result { Ok(Self::new(ValidatorNodeSignature::new( - PublicKey::from_bytes(&value.public_key).map_err(|e| e.to_string())?, + PublicKey::from_canonical_bytes(&value.public_key).map_err(|e| e.to_string())?, value .signature .map(Signature::try_from) @@ -114,7 +114,7 @@ impl TryFrom for CodeTemplateRegistration { fn try_from(value: proto::types::TemplateRegistration) -> Result { Ok(Self { - author_public_key: PublicKey::from_bytes(&value.author_public_key).map_err(|e| e.to_string())?, + author_public_key: PublicKey::from_canonical_bytes(&value.author_public_key).map_err(|e| e.to_string())?, author_signature: value .author_signature .map(Signature::try_from) @@ -159,7 +159,7 @@ impl TryFrom for ConfidentialOutputData { fn try_from(value: proto::types::ConfidentialOutputData) -> Result { Ok(ConfidentialOutputData { - claim_public_key: PublicKey::from_bytes(&value.claim_public_key).map_err(|e| e.to_string())?, + claim_public_key: PublicKey::from_canonical_bytes(&value.claim_public_key).map_err(|e| e.to_string())?, }) } } diff --git a/base_layer/core/src/proto/transaction.rs b/base_layer/core/src/proto/transaction.rs index 56f5c1a594..dbfc6dbdec 100644 --- a/base_layer/core/src/proto/transaction.rs +++ b/base_layer/core/src/proto/transaction.rs @@ -63,7 +63,7 @@ impl TryFrom for TransactionKernel { type Error = String; fn try_from(kernel: proto::types::TransactionKernel) -> Result { - let excess = Commitment::from_bytes( + let excess = Commitment::from_canonical_bytes( &kernel .excess .ok_or_else(|| "Excess not provided in kernel".to_string())? @@ -77,7 +77,9 @@ impl TryFrom for TransactionKernel { .try_into()?; let kernel_features = u8::try_from(kernel.features).map_err(|_| "Kernel features must be a single byte")?; let commitment = match kernel.burn_commitment { - Some(burn_commitment) => Some(Commitment::from_bytes(&burn_commitment.data).map_err(|e| e.to_string())?), + Some(burn_commitment) => { + Some(Commitment::from_canonical_bytes(&burn_commitment.data).map_err(|e| e.to_string())?) + }, None => None, }; @@ -125,14 +127,14 @@ impl TryFrom for TransactionInput { // Check if the received Transaction input is in compact form or not if let Some(commitment) = input.commitment { - let commitment = Commitment::from_bytes(&commitment.data).map_err(|e| e.to_string())?; + let commitment = Commitment::from_canonical_bytes(&commitment.data).map_err(|e| e.to_string())?; let features = input .features .map(TryInto::try_into) .ok_or_else(|| "transaction output features not provided".to_string())??; - let sender_offset_public_key = - PublicKey::from_bytes(input.sender_offset_public_key.as_bytes()).map_err(|err| format!("{:?}", err))?; + let sender_offset_public_key = PublicKey::from_canonical_bytes(input.sender_offset_public_key.as_bytes()) + .map_err(|err| format!("{:?}", err))?; let metadata_signature = input .metadata_signature @@ -263,15 +265,15 @@ impl TryFrom for TransactionOutput { let commitment = output .commitment - .map(|commit| Commitment::from_bytes(&commit.data)) + .map(|commit| Commitment::from_canonical_bytes(&commit.data)) .ok_or_else(|| "Transaction output commitment not provided".to_string())? .map_err(|err| err.to_string())?; - let sender_offset_public_key = - PublicKey::from_bytes(output.sender_offset_public_key.as_bytes()).map_err(|err| format!("{:?}", err))?; + let sender_offset_public_key = PublicKey::from_canonical_bytes(output.sender_offset_public_key.as_bytes()) + .map_err(|err| format!("{:?}", err))?; let range_proof = if let Some(proof) = output.range_proof { - Some(BulletRangeProof::from_bytes(&proof.proof_bytes).map_err(|err| err.to_string())?) + Some(BulletRangeProof::from_canonical_bytes(&proof.proof_bytes).map_err(|err| err.to_string())?) } else { None }; @@ -422,7 +424,7 @@ impl TryFrom for Transaction { fn try_from(tx: proto::types::Transaction) -> Result { let offset = tx .offset - .map(|offset| PrivateKey::from_bytes(&offset.data)) + .map(|offset| PrivateKey::from_canonical_bytes(&offset.data)) .ok_or_else(|| "Blinding factor offset not provided".to_string())? .map_err(|err| err.to_string())?; let body = tx @@ -431,7 +433,7 @@ impl TryFrom for Transaction { .ok_or_else(|| "Body not provided".to_string())??; let script_offset = tx .script_offset - .map(|script_offset| PrivateKey::from_bytes(&script_offset.data)) + .map(|script_offset| PrivateKey::from_canonical_bytes(&script_offset.data)) .ok_or_else(|| "Script offset not provided".to_string())? .map_err(|err| err.to_string())?; diff --git a/base_layer/core/src/proto/types_impls.rs b/base_layer/core/src/proto/types_impls.rs index 90c7b14174..6cf22b993c 100644 --- a/base_layer/core/src/proto/types_impls.rs +++ b/base_layer/core/src/proto/types_impls.rs @@ -36,7 +36,7 @@ impl TryFrom for Commitment { type Error = ByteArrayError; fn try_from(commitment: proto::Commitment) -> Result { - Commitment::from_bytes(&commitment.data) + Commitment::from_canonical_bytes(&commitment.data) } } @@ -53,8 +53,8 @@ impl TryFrom for Signature { type Error = String; fn try_from(sig: proto::Signature) -> Result { - let public_nonce = PublicKey::from_bytes(&sig.public_nonce).map_err(|e| e.to_string())?; - let signature = PrivateKey::from_bytes(&sig.signature).map_err(|e| e.to_string())?; + let public_nonce = PublicKey::from_canonical_bytes(&sig.public_nonce).map_err(|e| e.to_string())?; + let signature = PrivateKey::from_canonical_bytes(&sig.signature).map_err(|e| e.to_string())?; Ok(Self::new(public_nonce, signature)) } @@ -75,11 +75,11 @@ impl TryFrom for ComAndPubSignature { type Error = ByteArrayError; fn try_from(sig: proto::ComAndPubSignature) -> Result { - let ephemeral_commitment = Commitment::from_bytes(&sig.ephemeral_commitment)?; - let ephemeral_pubkey = PublicKey::from_bytes(&sig.ephemeral_pubkey)?; - let u_a = PrivateKey::from_bytes(&sig.u_a)?; - let u_x = PrivateKey::from_bytes(&sig.u_x)?; - let u_y = PrivateKey::from_bytes(&sig.u_y)?; + let ephemeral_commitment = Commitment::from_canonical_bytes(&sig.ephemeral_commitment)?; + let ephemeral_pubkey = PublicKey::from_canonical_bytes(&sig.ephemeral_pubkey)?; + let u_a = PrivateKey::from_canonical_bytes(&sig.u_a)?; + let u_x = PrivateKey::from_canonical_bytes(&sig.u_x)?; + let u_y = PrivateKey::from_canonical_bytes(&sig.u_y)?; Ok(Self::new(ephemeral_commitment, ephemeral_pubkey, u_a, u_x, u_y)) } @@ -122,7 +122,7 @@ impl TryFrom for PrivateKey { type Error = ByteArrayError; fn try_from(offset: proto::PrivateKey) -> Result { - PrivateKey::from_bytes(&offset.data) + PrivateKey::from_canonical_bytes(&offset.data) } } diff --git a/base_layer/core/src/transactions/coinbase_builder.rs b/base_layer/core/src/transactions/coinbase_builder.rs index 9ac6b9f19b..94e46d3ed2 100644 --- a/base_layer/core/src/transactions/coinbase_builder.rs +++ b/base_layer/core/src/transactions/coinbase_builder.rs @@ -309,8 +309,7 @@ where TKeyManagerInterface: TransactionKeyManagerInterface #[cfg(test)] mod test { use tari_common::configuration::Network; - use tari_common_types::types::{Commitment, PrivateKey}; - use tari_utilities::ByteArray; + use tari_common_types::types::Commitment; use crate::{ consensus::{emission::Emission, ConsensusManager, ConsensusManagerBuilder}, @@ -605,7 +604,7 @@ mod test { &excess, &kernel_message, ); - assert!(sig.verify(&excess, &PrivateKey::from_bytes(&sig_challenge).unwrap())); + assert!(sig.verify_raw_wide(&excess, &sig_challenge)); // we fix the signature and the excess with the now included offset. coinbase_kernel2.excess_sig = sig; diff --git a/base_layer/core/src/transactions/key_manager/inner.rs b/base_layer/core/src/transactions/key_manager/inner.rs index 8a4c2d2f15..c245be11a6 100644 --- a/base_layer/core/src/transactions/key_manager/inner.rs +++ b/base_layer/core/src/transactions/key_manager/inner.rs @@ -22,7 +22,7 @@ use std::{collections::HashMap, ops::Shl}; use blake2::Blake2b; -use digest::consts::U32; +use digest::consts::U64; use log::*; use rand::rngs::OsRng; use strum::IntoEnumIterator; @@ -379,7 +379,7 @@ where TBackend: KeyManagerBackend + 'static &self, secret_key_id: &TariKeyId, public_key: &PublicKey, - ) -> Result>, TransactionError> { + ) -> Result>, TransactionError> { let secret_key = self.get_private_key(secret_key_id).await?; Ok(diffie_hellman_stealth_domain_hasher(&secret_key, public_key)) } @@ -522,7 +522,7 @@ where TBackend: KeyManagerBackend + 'static let proof_bytes = proof_bytes_result .map_err(|err| TransactionError::RangeProofError(format!("Failed to construct range proof: {}", err)))?; - RangeProof::from_bytes(&proof_bytes).map_err(|_| { + RangeProof::from_canonical_bytes(&proof_bytes).map_err(|_| { TransactionError::RangeProofError("Rangeproof factory returned invalid range proof bytes".to_string()) }) } @@ -555,22 +555,22 @@ where TBackend: KeyManagerBackend + 'static // With RevealedValue type range proofs, the nonce is always 0 and the minimum value promise equal to the value let nonce_a = match range_proof_type { RangeProofType::BulletProofPlus => { - let hasher_a = DomainSeparatedHasher::, KeyManagerHashingDomain>::new_with_label( + let hasher_a = DomainSeparatedHasher::, KeyManagerHashingDomain>::new_with_label( "metadata_signature_ephemeral_nonce_a", ); let a_hash = hasher_a.chain(nonce_private_key.as_bytes()).finalize(); - PrivateKey::from_bytes(a_hash.as_ref()).map_err(|_| { + PrivateKey::from_bytes_wide(a_hash.as_ref()).map_err(|_| { TransactionError::KeyManagerError("Invalid private key for sender offset private key".to_string()) }) }, RangeProofType::RevealedValue => Ok(PrivateKey::default()), }?; - let hasher_b = DomainSeparatedHasher::, KeyManagerHashingDomain>::new_with_label( + let hasher_b = DomainSeparatedHasher::, KeyManagerHashingDomain>::new_with_label( "metadata_signature_ephemeral_nonce_b", ); let b_hash = hasher_b.chain(nonce_private_key.as_bytes()).finalize(); - let nonce_b = PrivateKey::from_bytes(b_hash.as_ref()).map_err(|_| { + let nonce_b = PrivateKey::from_bytes_wide(b_hash.as_ref()).map_err(|_| { TransactionError::KeyManagerError("Invalid private key for sender offset private key".to_string()) })?; Ok((nonce_a, nonce_b)) @@ -753,14 +753,14 @@ where TBackend: KeyManagerBackend + 'static nonce_id: &TariKeyId, ) -> Result { let hasher = - DomainSeparatedHasher::, KeyManagerHashingDomain>::new_with_label("kernel_excess_offset"); + DomainSeparatedHasher::, KeyManagerHashingDomain>::new_with_label("kernel_excess_offset"); let spending_private_key = self.get_private_key(spend_key_id).await?; let nonce_private_key = self.get_private_key(nonce_id).await?; let key_hash = hasher .chain(spending_private_key.as_bytes()) .chain(nonce_private_key.as_bytes()) .finalize(); - PrivateKey::from_bytes(key_hash.as_ref()).map_err(|_| { + PrivateKey::from_bytes_wide(key_hash.as_ref()).map_err(|_| { TransactionError::KeyManagerError("Invalid private key for kernel signature nonce".to_string()) }) } @@ -802,7 +802,7 @@ where TBackend: KeyManagerBackend + 'static kernel_message, ); - let signature = Signature::sign_raw(&final_signing_key, private_nonce, &challenge)?; + let signature = Signature::sign_raw_wide(&final_signing_key, private_nonce, &challenge)?; Ok(signature) } diff --git a/base_layer/core/src/transactions/key_manager/interface.rs b/base_layer/core/src/transactions/key_manager/interface.rs index 65ac0f49ba..ff3082e72a 100644 --- a/base_layer/core/src/transactions/key_manager/interface.rs +++ b/base_layer/core/src/transactions/key_manager/interface.rs @@ -21,7 +21,7 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use blake2::Blake2b; -use digest::consts::U32; +use digest::consts::U64; use strum_macros::EnumIter; use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, RangeProof, Signature}; use tari_comms::types::CommsDHKE; @@ -117,7 +117,7 @@ pub trait TransactionKeyManagerInterface: KeyManagerInterface { &self, secret_key_id: &TariKeyId, public_key: &PublicKey, - ) -> Result>, TransactionError>; + ) -> Result>, TransactionError>; async fn import_add_offset_to_private_key( &self, diff --git a/base_layer/core/src/transactions/key_manager/wrapper.rs b/base_layer/core/src/transactions/key_manager/wrapper.rs index b0a6487684..2823c55db2 100644 --- a/base_layer/core/src/transactions/key_manager/wrapper.rs +++ b/base_layer/core/src/transactions/key_manager/wrapper.rs @@ -23,7 +23,7 @@ use std::sync::Arc; use blake2::Blake2b; -use digest::consts::U32; +use digest::consts::U64; use tari_common_types::types::{ComAndPubSignature, Commitment, PrivateKey, PublicKey, RangeProof, Signature}; use tari_comms::types::CommsDHKE; use tari_crypto::{hashing::DomainSeparatedHash, ristretto::RistrettoComSig}; @@ -234,7 +234,7 @@ where TBackend: KeyManagerBackend + 'static &self, secret_key_id: &TariKeyId, public_key: &PublicKey, - ) -> Result>, TransactionError> { + ) -> Result>, TransactionError> { self.transaction_key_manager_inner .read() .await diff --git a/base_layer/core/src/transactions/test_helpers.rs b/base_layer/core/src/transactions/test_helpers.rs index df0709005e..d27778e603 100644 --- a/base_layer/core/src/transactions/test_helpers.rs +++ b/base_layer/core/src/transactions/test_helpers.rs @@ -266,7 +266,7 @@ pub fn create_signature(k: PrivateKey, fee: MicroMinotari, lock_height: u64, fea &PublicKey::from_secret_key(&k), &tx_meta, ); - Signature::sign_raw(&k, r, &e).unwrap() + Signature::sign_raw_wide(&k, r, &e).unwrap() } /// Generate a random transaction signature given a key, returning the public key (excess) and the signature. diff --git a/base_layer/core/src/transactions/transaction_components/encrypted_data.rs b/base_layer/core/src/transactions/transaction_components/encrypted_data.rs index bf353e6acb..fb39d3e37b 100644 --- a/base_layer/core/src/transactions/transaction_components/encrypted_data.rs +++ b/base_layer/core/src/transactions/transaction_components/encrypted_data.rs @@ -135,7 +135,7 @@ impl EncryptedData { value_bytes.clone_from_slice(&bytes[0..SIZE_VALUE]); Ok(( u64::from_le_bytes(value_bytes).into(), - PrivateKey::from_bytes(&bytes[SIZE_VALUE..])?, + PrivateKey::from_canonical_bytes(&bytes[SIZE_VALUE..])?, )) } diff --git a/base_layer/core/src/transactions/transaction_components/mod.rs b/base_layer/core/src/transactions/transaction_components/mod.rs index 5661f11e10..9011bb0185 100644 --- a/base_layer/core/src/transactions/transaction_components/mod.rs +++ b/base_layer/core/src/transactions/transaction_components/mod.rs @@ -23,7 +23,9 @@ // Portions of this file were originally copyrighted (c) 2018 The Grin Developers, issued under the Apache License, // Version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0. +use blake2::Blake2b; use chacha20poly1305::Key; +use digest::consts::U32; pub use encrypted_data::{EncryptedData, EncryptedDataError}; pub use error::TransactionError; pub use kernel_builder::KernelBuilder; @@ -109,7 +111,7 @@ pub(super) fn hash_output( encrypted_data: &EncryptedData, minimum_value_promise: MicroMinotari, ) -> FixedHash { - let common_hash = DomainSeparatedConsensusHasher::::new("transaction_output") + let common_hash = DomainSeparatedConsensusHasher::>::new("transaction_output") .chain(&version) .chain(features) .chain(commitment) diff --git a/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_registration.rs b/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_registration.rs index a5e9fec208..17db00a145 100644 --- a/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_registration.rs +++ b/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_registration.rs @@ -20,7 +20,9 @@ // 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. +use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; +use digest::consts::U32; use serde::{Deserialize, Serialize}; use tari_common_types::{ epoch::VnEpoch, @@ -84,7 +86,7 @@ fn does_require_new_shard_key(public_key: &PublicKey, epoch: VnEpoch, interval: } fn generate_shard_key(public_key: &PublicKey, entropy: &[u8; 32]) -> [u8; 32] { - DomainSeparatedConsensusHasher::::new("validator_node_shard_key") + DomainSeparatedConsensusHasher::>::new("validator_node_shard_key") .chain(public_key) .chain(entropy) .finalize() diff --git a/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_signature.rs b/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_signature.rs index cc74ff4f8e..0a64c6f6e6 100644 --- a/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_signature.rs +++ b/base_layer/core/src/transactions/transaction_components/side_chain/validator_node_signature.rs @@ -22,10 +22,10 @@ use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; -use digest::consts::U32; +use digest::consts::U64; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; -use tari_common_types::types::{FixedHash, PrivateKey, PublicKey, Signature}; +use tari_common_types::types::{PrivateKey, PublicKey, Signature}; use tari_crypto::{hash_domain, hashing::DomainSeparatedHasher, keys::PublicKey as PublicKeyT}; use tari_utilities::ByteArray; @@ -50,13 +50,13 @@ impl ValidatorNodeSignature { let (secret_nonce, public_nonce) = PublicKey::random_keypair(&mut OsRng); let public_key = PublicKey::from_secret_key(private_key); let challenge = Self::construct_challenge(&public_key, &public_nonce, msg); - let signature = Signature::sign_raw(private_key, secret_nonce, &*challenge) - .expect("Sign cannot fail with 32-byte challenge and a RistrettoPublicKey"); + let signature = Signature::sign_raw_wide(private_key, secret_nonce, &challenge) + .expect("Sign cannot fail with 64-byte challenge and a RistrettoPublicKey"); Self { public_key, signature } } - fn construct_challenge(public_key: &PublicKey, public_nonce: &PublicKey, msg: &[u8]) -> FixedHash { - let hasher = DomainSeparatedHasher::, ValidatorNodeHashDomain>::new_with_label("registration") + fn construct_challenge(public_key: &PublicKey, public_nonce: &PublicKey, msg: &[u8]) -> [u8; 64] { + let hasher = DomainSeparatedHasher::, ValidatorNodeHashDomain>::new_with_label("registration") .chain(public_key.as_bytes()) .chain(public_nonce.as_bytes()) .chain(msg); @@ -65,7 +65,7 @@ impl ValidatorNodeSignature { pub fn is_valid_signature_for(&self, msg: &[u8]) -> bool { let challenge = Self::construct_challenge(&self.public_key, self.signature.get_public_nonce(), msg); - self.signature.verify_challenge(&self.public_key, &*challenge) + self.signature.verify_raw_wide(&self.public_key, &challenge) } pub fn public_key(&self) -> &PublicKey { diff --git a/base_layer/core/src/transactions/transaction_components/transaction_input.rs b/base_layer/core/src/transactions/transaction_components/transaction_input.rs index a3494c6db1..3cc09fe84b 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_input.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_input.rs @@ -28,7 +28,9 @@ use std::{ fmt::{Display, Formatter}, }; +use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; +use digest::consts::{U32, U64}; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; use tari_common_types::types::{ComAndPubSignature, Commitment, CommitmentFactory, FixedHash, HashOutput, PublicKey}; @@ -175,7 +177,7 @@ impl TransactionInput { input_data: &ExecutionStack, script_public_key: &PublicKey, commitment: &Commitment, - ) -> [u8; 32] { + ) -> [u8; 64] { // We build the message separately to help with hardware wallet support. This reduces the amount of data that // needs to be transferred in order to sign the signature. let message = TransactionInput::build_script_signature_message(version, script, input_data); @@ -197,10 +199,10 @@ impl TransactionInput { script_public_key: &PublicKey, commitment: &Commitment, message: &[u8; 32], - ) -> [u8; 32] { + ) -> [u8; 64] { match version { TransactionInputVersion::V0 | TransactionInputVersion::V1 => { - DomainSeparatedConsensusHasher::::new("script_challenge") + DomainSeparatedConsensusHasher::>::new("script_challenge") .chain(ephemeral_commitment) .chain(ephemeral_pubkey) .chain(script_public_key) @@ -220,7 +222,7 @@ impl TransactionInput { ) -> [u8; 32] { match version { TransactionInputVersion::V0 | TransactionInputVersion::V1 => { - DomainSeparatedConsensusHasher::::new("script_message") + DomainSeparatedConsensusHasher::>::new("script_message") .chain(version) .chain(script) .chain(input_data) @@ -456,7 +458,7 @@ impl TransactionInput { /// Implement the canonical hashing function for TransactionInput for use in ordering pub fn canonical_hash(&self) -> FixedHash { - let writer = DomainSeparatedConsensusHasher::::new("transaction_input") + let writer = DomainSeparatedConsensusHasher::>::new("transaction_input") .chain(&self.version) .chain(&self.script_signature) .chain(&self.input_data) diff --git a/base_layer/core/src/transactions/transaction_components/transaction_kernel.rs b/base_layer/core/src/transactions/transaction_components/transaction_kernel.rs index c33f1bb159..f561931c37 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_kernel.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_kernel.rs @@ -28,7 +28,9 @@ use std::{ fmt::{Display, Formatter}, }; +use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; +use digest::consts::{U32, U64}; use serde::{Deserialize, Serialize}; use tari_common_types::types::{Commitment, FixedHash, PublicKey, Signature}; use tari_utilities::{hex::Hex, message_format::MessageFormat}; @@ -92,7 +94,7 @@ impl TransactionKernel { /// Produce a canonical hash for a transaction kernel. pub fn hash(&self) -> FixedHash { - DomainSeparatedConsensusHasher::::new("transaction_kernel") + DomainSeparatedConsensusHasher::>::new("transaction_kernel") .chain(self) .finalize() .into() @@ -138,7 +140,7 @@ impl TransactionKernel { &self.features, &self.burn_commitment, ); - if self.excess_sig.verify_challenge(excess, &c) { + if self.excess_sig.verify_raw_wide(excess, &c) { Ok(()) } else { Err(TransactionError::InvalidSignatureError( @@ -162,7 +164,7 @@ impl TransactionKernel { sum_public_nonces: &PublicKey, total_excess: &PublicKey, tx_meta: &TransactionMetadata, - ) -> [u8; 32] { + ) -> [u8; 64] { TransactionKernel::build_kernel_signature_challenge( version, sum_public_nonces, @@ -189,7 +191,7 @@ impl TransactionKernel { lock_height: u64, features: &KernelFeatures, burn_commitment: &Option, - ) -> [u8; 32] { + ) -> [u8; 64] { // We build the message separately to help with hardware wallet support. This reduces the amount of data that // needs to be transferred in order to sign the signature. let message = @@ -203,8 +205,8 @@ impl TransactionKernel { sum_public_nonces: &PublicKey, total_excess: &PublicKey, message: &[u8; 32], - ) -> [u8; 32] { - let common = DomainSeparatedConsensusHasher::::new("kernel_signature") + ) -> [u8; 64] { + let common = DomainSeparatedConsensusHasher::>::new("kernel_signature") .chain(sum_public_nonces) .chain(total_excess) .chain(message); @@ -222,7 +224,7 @@ impl TransactionKernel { features: &KernelFeatures, burn_commitment: &Option, ) -> [u8; 32] { - let common = DomainSeparatedConsensusHasher::::new("kernel_message") + let common = DomainSeparatedConsensusHasher::>::new("kernel_message") .chain(version) .chain(&fee) .chain(&lock_height) diff --git a/base_layer/core/src/transactions/transaction_components/transaction_output.rs b/base_layer/core/src/transactions/transaction_components/transaction_output.rs index 2dcf623a34..e2326f25ae 100644 --- a/base_layer/core/src/transactions/transaction_components/transaction_output.rs +++ b/base_layer/core/src/transactions/transaction_components/transaction_output.rs @@ -28,7 +28,9 @@ use std::{ fmt::{Display, Formatter}, }; +use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; +use digest::consts::{U32, U64}; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; use tari_common_types::types::{ @@ -45,6 +47,7 @@ use tari_crypto::{ commitment::HomomorphicCommitmentFactory, errors::RangeProofError, extended_range_proof::{ExtendedRangeProofService, Statement}, + keys::SecretKey, ristretto::bulletproofs_plus::RistrettoAggregatedPublicStatement, tari_utilities::{hex::Hex, ByteArray}, }; @@ -276,7 +279,7 @@ impl TransactionOutput { }, }; // Now we can perform the balance proof - let e = PrivateKey::from_bytes(&e_bytes).unwrap(); + let e = PrivateKey::from_bytes_wide(&e_bytes).unwrap(); let value_as_private_key = PrivateKey::from(self.minimum_value_promise.as_u64()); let commit_nonce_a = PrivateKey::default(); // This is the deterministic nonce `r_a` of zero if self.metadata_signature.u_a().to_hex() == (commit_nonce_a + e * value_as_private_key).to_hex() { @@ -291,7 +294,7 @@ impl TransactionOutput { } } - fn verify_metadata_signature_internal(&self) -> Result<[u8; 32], TransactionError> { + fn verify_metadata_signature_internal(&self) -> Result<[u8; 64], TransactionError> { let challenge = TransactionOutput::build_metadata_signature_challenge( &self.version, &self.script, @@ -379,7 +382,7 @@ impl TransactionOutput { covenant: &Covenant, encrypted_data: &EncryptedData, minimum_value_promise: MicroMinotari, - ) -> [u8; 32] { + ) -> [u8; 64] { // We build the message separately to help with hardware wallet support. This reduces the amount of data that // needs to be transferred in order to sign the signature. let message = TransactionOutput::metadata_signature_message_from_parts( @@ -407,8 +410,8 @@ impl TransactionOutput { ephemeral_pubkey: &PublicKey, commitment: &Commitment, message: &[u8; 32], - ) -> [u8; 32] { - let common = DomainSeparatedConsensusHasher::::new("metadata_signature") + ) -> [u8; 64] { + let common = DomainSeparatedConsensusHasher::>::new("metadata_signature") .chain(ephemeral_pubkey) .chain(ephemeral_commitment) .chain(sender_offset_public_key) @@ -442,7 +445,7 @@ impl TransactionOutput { encrypted_data: &EncryptedData, minimum_value_promise: &MicroMinotari, ) -> [u8; 32] { - let common = DomainSeparatedConsensusHasher::::new("metadata_message") + let common = DomainSeparatedConsensusHasher::>::new("metadata_message") .chain(version) .chain(script) .chain(features) diff --git a/base_layer/core/src/transactions/transaction_protocol/proto/recipient_signed_message.rs b/base_layer/core/src/transactions/transaction_protocol/proto/recipient_signed_message.rs index 723022ab99..8960b9b574 100644 --- a/base_layer/core/src/transactions/transaction_protocol/proto/recipient_signed_message.rs +++ b/base_layer/core/src/transactions/transaction_protocol/proto/recipient_signed_message.rs @@ -37,8 +37,8 @@ impl TryFrom for RecipientSignedMessage { .map(TryInto::try_into) .ok_or_else(|| "Transaction output not provided".to_string())??; - let public_spend_key = - PublicKey::from_bytes(&message.public_spend_key).map_err(|err| format!("public_spend_key: {}", err))?; + let public_spend_key = PublicKey::from_canonical_bytes(&message.public_spend_key) + .map_err(|err| format!("public_spend_key: {}", err))?; let partial_signature = message .partial_signature @@ -49,7 +49,7 @@ impl TryFrom for RecipientSignedMessage { .map(TryInto::try_into) .ok_or_else(|| "Transaction metadata not provided".to_string())??; - let offset = PrivateKey::from_bytes(&message.offset).map_err(|err| format!("offset: {}", err))?; + let offset = PrivateKey::from_canonical_bytes(&message.offset).map_err(|err| format!("offset: {}", err))?; Ok(Self { tx_id: message.tx_id.into(), diff --git a/base_layer/core/src/transactions/transaction_protocol/proto/transaction_metadata.rs b/base_layer/core/src/transactions/transaction_protocol/proto/transaction_metadata.rs index f95f2d44b8..ca57d05658 100644 --- a/base_layer/core/src/transactions/transaction_protocol/proto/transaction_metadata.rs +++ b/base_layer/core/src/transactions/transaction_protocol/proto/transaction_metadata.rs @@ -37,7 +37,8 @@ impl TryFrom for TransactionMetadata { let commitment = metadata .burned_commitment .map(|burned_commitment| { - Commitment::from_bytes(&burned_commitment.data).map_err(|e| format!("burned_commitment.data: {}", e)) + Commitment::from_canonical_bytes(&burned_commitment.data) + .map_err(|e| format!("burned_commitment.data: {}", e)) }) .transpose()?; Ok(Self { diff --git a/base_layer/core/src/transactions/transaction_protocol/proto/transaction_sender.rs b/base_layer/core/src/transactions/transaction_protocol/proto/transaction_sender.rs index 86c7bc0cd2..2f7c4f86bb 100644 --- a/base_layer/core/src/transactions/transaction_protocol/proto/transaction_sender.rs +++ b/base_layer/core/src/transactions/transaction_protocol/proto/transaction_sender.rs @@ -91,17 +91,17 @@ impl TryFrom for SingleRoundSenderData { type Error = String; fn try_from(data: proto::SingleRoundSenderData) -> Result { - let public_excess = PublicKey::from_bytes(&data.public_excess).map_err(|err| err.to_string())?; - let public_nonce = PublicKey::from_bytes(&data.public_nonce).map_err(|err| err.to_string())?; + let public_excess = PublicKey::from_canonical_bytes(&data.public_excess).map_err(|err| err.to_string())?; + let public_nonce = PublicKey::from_canonical_bytes(&data.public_nonce).map_err(|err| err.to_string())?; let sender_offset_public_key = - PublicKey::from_bytes(&data.sender_offset_public_key).map_err(|err| err.to_string())?; + PublicKey::from_canonical_bytes(&data.sender_offset_public_key).map_err(|err| err.to_string())?; let metadata = data .metadata .map(TryInto::try_into) .ok_or_else(|| "Transaction metadata not provided".to_string())??; let message = data.message; let ephemeral_public_nonce = - PublicKey::from_bytes(&data.ephemeral_public_nonce).map_err(|err| err.to_string())?; + PublicKey::from_canonical_bytes(&data.ephemeral_public_nonce).map_err(|err| err.to_string())?; let features = data .features .map(TryInto::try_into) diff --git a/base_layer/core/src/transactions/transaction_protocol/single_receiver.rs b/base_layer/core/src/transactions/transaction_protocol/single_receiver.rs index f4941d8ba0..9fce021b69 100644 --- a/base_layer/core/src/transactions/transaction_protocol/single_receiver.rs +++ b/base_layer/core/src/transactions/transaction_protocol/single_receiver.rs @@ -345,7 +345,7 @@ mod test { &m, ); assert!( - prot.partial_signature.verify_challenge(&signing_pubkey, &e), + prot.partial_signature.verify_raw_wide(&signing_pubkey, &e), "Partial signature is incorrect" ); } diff --git a/base_layer/key_manager/src/key_manager.rs b/base_layer/key_manager/src/key_manager.rs index a72b7d1958..e14b7fa240 100644 --- a/base_layer/key_manager/src/key_manager.rs +++ b/base_layer/key_manager/src/key_manager.rs @@ -23,14 +23,13 @@ use std::marker::PhantomData; use derivative::Derivative; -use digest::Digest; +use digest::{consts::U64, typenum::IsEqual, Digest}; use serde::{Deserialize, Serialize}; use tari_crypto::{ hashing::LengthExtensionAttackResistant, - keys::PublicKey, + keys::{PublicKey, SecretKey}, tari_utilities::byte_array::ByteArrayError, }; -use tari_utilities::ByteArray; use zeroize::Zeroize; use crate::{cipher_seed::CipherSeed, mac_domain_hasher, LABEL_DERIVE_KEY}; @@ -73,6 +72,7 @@ impl KeyManager where PK: PublicKey, D: Digest + LengthExtensionAttackResistant, + D::OutputSize: IsEqual, { /// Creates a new KeyManager with a new randomly selected entropy pub fn new() -> KeyManager { @@ -109,7 +109,7 @@ where .finalize(); let derive_key = derive_key.as_ref(); - let s = ::from_bytes(derive_key)?; + let s = ::from_bytes_wide(derive_key)?; Ok(s) } @@ -164,6 +164,7 @@ impl Default for KeyManager where K: PublicKey, D: Digest + LengthExtensionAttackResistant, + D::OutputSize: IsEqual, { fn default() -> Self { Self::new() @@ -173,21 +174,21 @@ where #[cfg(test)] mod test { use blake2::Blake2b; - use digest::consts::U32; + use digest::consts::U64; use tari_crypto::ristretto::RistrettoPublicKey; use crate::key_manager::*; #[test] fn test_new_keymanager() { - let km1 = KeyManager::>::new(); - let km2 = KeyManager::>::new(); + let km1 = KeyManager::>::new(); + let km2 = KeyManager::>::new(); assert_ne!(km1.seed, km2.seed); } #[test] fn test_derive_and_next_key() { - let mut km = KeyManager::>::new(); + let mut km = KeyManager::>::new(); let next_key1_result = km.next_key(); let next_key2_result = km.next_key(); let desired_key_index1 = 1; @@ -207,7 +208,7 @@ mod test { #[test] fn test_derive_and_next_key_with_branch_seed() { - let mut km = KeyManager::>::from(CipherSeed::new(), "Test".to_string(), 0); + let mut km = KeyManager::>::from(CipherSeed::new(), "Test".to_string(), 0); let next_key1_result = km.next_key(); let next_key2_result = km.next_key(); let desired_key_index1 = 1; @@ -228,8 +229,8 @@ mod test { #[test] fn test_use_of_branch_seed() { let x = CipherSeed::new(); - let mut km1 = KeyManager::>::from(x.clone(), "some".to_string(), 0); - let mut km2 = KeyManager::>::from(x, "other".to_string(), 0); + let mut km1 = KeyManager::>::from(x.clone(), "some".to_string(), 0); + let mut km2 = KeyManager::>::from(x, "other".to_string(), 0); let next_key1 = km1.next_key().unwrap(); let next_key2 = km2.next_key().unwrap(); assert_ne!(next_key1.key, next_key2.key); diff --git a/base_layer/key_manager/src/key_manager_service/mod.rs b/base_layer/key_manager/src/key_manager_service/mod.rs index 486e04fbca..d5670676c4 100644 --- a/base_layer/key_manager/src/key_manager_service/mod.rs +++ b/base_layer/key_manager/src/key_manager_service/mod.rs @@ -31,10 +31,10 @@ // any unwanted changes) use blake2::Blake2b; -use digest::consts::U32; +use digest::consts::U64; /// Specify the Hash function used by the key manager -pub type KeyDigest = Blake2b; +pub type KeyDigest = Blake2b; mod error; pub use error::KeyManagerServiceError; diff --git a/base_layer/wallet/src/output_manager_service/service.rs b/base_layer/wallet/src/output_manager_service/service.rs index 4949b07c24..d99021af50 100644 --- a/base_layer/wallet/src/output_manager_service/service.rs +++ b/base_layer/wallet/src/output_manager_service/service.rs @@ -59,6 +59,7 @@ use tari_core::{ SenderTransactionProtocol, }, }; +use tari_crypto::keys::SecretKey; use tari_script::{inputs, script, ExecutionStack, Opcode, TariScript}; use tari_service_framework::reply_channel; use tari_shutdown::ShutdownSignal; @@ -2394,7 +2395,7 @@ where } // Compute the stealth address offset - let stealth_address_offset = PrivateKey::from_bytes(stealth_address_hasher.as_ref()) + let stealth_address_offset = PrivateKey::from_bytes_wide(stealth_address_hasher.as_ref()) .expect("'DomainSeparatedHash>' has correct size"); let stealth_key = self .resources diff --git a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs index 265eebdcdb..f98403a549 100644 --- a/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs +++ b/base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs @@ -740,7 +740,7 @@ impl OutputSql { encrypted_data, MicroMinotari::from(self.minimum_value_promise as u64), match self.rangeproof { - Some(bytes) => Some(RangeProof::from_bytes(&bytes)?), + Some(bytes) => Some(RangeProof::from_canonical_bytes(&bytes)?), None => None, }, ); diff --git a/base_layer/wallet/src/transaction_service/service.rs b/base_layer/wallet/src/transaction_service/service.rs index 54d3525825..89ea313010 100644 --- a/base_layer/wallet/src/transaction_service/service.rs +++ b/base_layer/wallet/src/transaction_service/service.rs @@ -3081,7 +3081,8 @@ mod tests { let receiver_spending_key = stealth_address_script_spending_key(&c, &big_b); // computing a scanning key `Ks=cG+B` for comparison - let scanning_key = PublicKey::from_secret_key(&RistrettoSecretKey::from_bytes(c.as_ref()).unwrap()) + big_b; + let scanning_key = + PublicKey::from_secret_key(&RistrettoSecretKey::from_bytes_wide(c.as_ref()).unwrap()) + big_b; assert_eq!(provided_spending_key.as_ref(), &sender_spending_key); assert_eq!(receiver_spending_key, sender_spending_key); diff --git a/base_layer/wallet/src/wallet.rs b/base_layer/wallet/src/wallet.rs index 86963e9642..ce38426b16 100644 --- a/base_layer/wallet/src/wallet.rs +++ b/base_layer/wallet/src/wallet.rs @@ -505,7 +505,7 @@ where secret: &PrivateKey, message: &str, ) -> Result, SchnorrSignatureError> { - SignatureWithDomain::::sign_message(secret, message.as_bytes(), &mut OsRng) + SignatureWithDomain::::sign(secret, message.as_bytes(), &mut OsRng) } pub fn verify_message_signature( @@ -514,7 +514,7 @@ where signature: &SignatureWithDomain, message: &str, ) -> bool { - signature.verify_message(public_key, message) + signature.verify(public_key, message) } /// Appraise the expected outputs and a fee diff --git a/base_layer/wallet/tests/transaction_service_tests/service.rs b/base_layer/wallet/tests/transaction_service_tests/service.rs index a057900ced..5b5ed4bdfb 100644 --- a/base_layer/wallet/tests/transaction_service_tests/service.rs +++ b/base_layer/wallet/tests/transaction_service_tests/service.rs @@ -832,7 +832,7 @@ async fn single_transaction_burn_tari() { .chain(&burn_proof.commitment) .chain(&claim_public_key) .finalize(); - let challenge = PrivateKey::from_bytes(&challenge_bytes).unwrap(); + let challenge = PrivateKey::from_bytes_wide(&challenge_bytes).unwrap(); assert!(burn_proof.ownership_proof.unwrap().verify( &burn_proof.commitment, &challenge, diff --git a/base_layer/wallet_ffi/src/ffi_basenode_state.rs b/base_layer/wallet_ffi/src/ffi_basenode_state.rs index 7c7d06e45b..4d2880900b 100644 --- a/base_layer/wallet_ffi/src/ffi_basenode_state.rs +++ b/base_layer/wallet_ffi/src/ffi_basenode_state.rs @@ -363,7 +363,7 @@ mod tests { assert_eq!( original_node_id, - NodeId::from_bytes((*wrapped_node_id).0.as_bytes()).unwrap() + NodeId::from_canonical_bytes((*wrapped_node_id).0.as_bytes()).unwrap() ); assert_eq!(error_code, 0); diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index 2df07af8bf..cd178042f9 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -887,7 +887,7 @@ pub unsafe extern "C" fn public_key_create(bytes: *mut ByteVector, error_out: *m return ptr::null_mut(); } let v = (*bytes).0.clone(); - let pk = TariPublicKey::from_bytes(&v); + let pk = TariPublicKey::from_canonical_bytes(&v); match pk { Ok(pk) => Box::into_raw(Box::new(pk)), Err(e) => { @@ -1340,7 +1340,7 @@ pub unsafe extern "C" fn commitment_and_public_signature_create_from_bytes( return ptr::null_mut(); } - let ephemeral_commitment = match Commitment::from_bytes(&(*ephemeral_commitment_bytes).0.clone()) { + let ephemeral_commitment = match Commitment::from_canonical_bytes(&(*ephemeral_commitment_bytes).0.clone()) { Ok(ephemeral_commitment) => ephemeral_commitment, Err(e) => { error!( @@ -1352,7 +1352,7 @@ pub unsafe extern "C" fn commitment_and_public_signature_create_from_bytes( return ptr::null_mut(); }, }; - let ephemeral_pubkey = match PublicKey::from_bytes(&(*ephemeral_pubkey_bytes).0.clone()) { + let ephemeral_pubkey = match PublicKey::from_canonical_bytes(&(*ephemeral_pubkey_bytes).0.clone()) { Ok(ephemeral_pubkey) => ephemeral_pubkey, Err(e) => { error!( @@ -1365,7 +1365,7 @@ pub unsafe extern "C" fn commitment_and_public_signature_create_from_bytes( }, }; - let u_a = match TariPrivateKey::from_bytes(&(*u_a_bytes).0.clone()) { + let u_a = match TariPrivateKey::from_canonical_bytes(&(*u_a_bytes).0.clone()) { Ok(u) => u, Err(e) => { error!( @@ -1377,7 +1377,7 @@ pub unsafe extern "C" fn commitment_and_public_signature_create_from_bytes( return ptr::null_mut(); }, }; - let u_x = match TariPrivateKey::from_bytes(&(*u_x_bytes).0.clone()) { + let u_x = match TariPrivateKey::from_canonical_bytes(&(*u_x_bytes).0.clone()) { Ok(u) => u, Err(e) => { error!( @@ -1389,7 +1389,7 @@ pub unsafe extern "C" fn commitment_and_public_signature_create_from_bytes( return ptr::null_mut(); }, }; - let u_y = match TariPrivateKey::from_bytes(&(*u_y_bytes).0.clone()) { + let u_y = match TariPrivateKey::from_canonical_bytes(&(*u_y_bytes).0.clone()) { Ok(u) => u, Err(e) => { error!( @@ -1953,7 +1953,7 @@ pub unsafe extern "C" fn private_key_create(bytes: *mut ByteVector, error_out: * return ptr::null_mut(); } let v = (*bytes).0.clone(); - let pk = TariPrivateKey::from_bytes(&v); + let pk = TariPrivateKey::from_canonical_bytes(&v); match pk { Ok(pk) => Box::into_raw(Box::new(pk)), Err(e) => { diff --git a/base_layer/wallet_ffi/wallet.h b/base_layer/wallet_ffi/wallet.h index 86c90bcaf5..db1a525a42 100644 --- a/base_layer/wallet_ffi/wallet.h +++ b/base_layer/wallet_ffi/wallet.h @@ -116,7 +116,7 @@ struct P2pConfig; * use tari_utilities::{hex::Hex, ByteArray}; * * let mut rng = rand::thread_rng(); - * let _p1 = RistrettoPublicKey::from_bytes(&[ + * let _p1 = RistrettoPublicKey::from_canonical_bytes(&[ * 224, 196, 24, 247, 200, 217, 196, 205, 215, 57, 91, 147, 234, 18, 79, 58, 217, 144, 33, * 187, 104, 29, 252, 51, 2, 169, 217, 154, 46, 83, 230, 78, * ]); @@ -144,7 +144,7 @@ struct RistrettoPublicKey; * use tari_utilities::{hex::Hex, ByteArray}; * * let mut rng = rand::thread_rng(); - * let _k1 = RistrettoSecretKey::from_bytes(&[ + * let _k1 = RistrettoSecretKey::from_canonical_bytes(&[ * 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, * 0, 0, * ]); @@ -252,9 +252,18 @@ typedef struct TariAddress TariWalletAddress; * "8063d85e151abee630e643e2b3dc47bfaeb8aa859c9d10d60847985f286aad19", * ) * .unwrap(); - * let u_a = RistrettoSecretKey::from_bytes(b"10000000000000000000000010000000").unwrap(); - * let u_x = RistrettoSecretKey::from_bytes(b"a00000000000000000000000a0000000").unwrap(); - * let u_y = RistrettoSecretKey::from_bytes(b"a00000000000000000000000a0000000").unwrap(); + * let u_a = RistrettoSecretKey::from_hex( + * "a8fb609c5ab7cc07548b076b6c25cc3237c4526fb7a6dcb83b26f457b172c20a", + * ) + * .unwrap(); + * let u_x = RistrettoSecretKey::from_hex( + * "0e689df8ad4ad9d2fd5aaf8cb0a66d85cb0d4b7a380405514d453625813b0b0f", + * ) + * .unwrap(); + * let u_y = RistrettoSecretKey::from_hex( + * "f494050bd0d4ed0ec514cdce9430d0564df6b35d2a12b7daa0e99c7d94a06509", + * ) + * .unwrap(); * let sig = RistrettoComAndPubSig::new(ephemeral_commitment, ephemeral_pubkey, u_a, u_x, u_y); * ``` * @@ -270,7 +279,7 @@ typedef struct TariAddress TariWalletAddress; * # use tari_crypto::ristretto::pedersen::*; * use tari_crypto::ristretto::pedersen::commitment_factory::PedersenCommitmentFactory; * use tari_utilities::hex::Hex; - * use digest::consts::U32; + * use digest::consts::U64; * * let mut rng = rand::thread_rng(); * let a_val = RistrettoSecretKey::random(&mut rng); @@ -279,7 +288,7 @@ typedef struct TariAddress TariWalletAddress; * let a_nonce = RistrettoSecretKey::random(&mut rng); * let x_nonce = RistrettoSecretKey::random(&mut rng); * let y_nonce = RistrettoSecretKey::random(&mut rng); - * let e = Blake2b::::digest(b"Maskerade"); // In real life, this should be strong Fiat-Shamir! + * let e = Blake2b::::digest(b"Maskerade"); // In real life, this should be strong Fiat-Shamir! * let factory = PedersenCommitmentFactory::default(); * let commitment = factory.commit(&x_val, &a_val); * let pubkey = RistrettoPublicKey::from_secret_key(&y_val); diff --git a/comms/core/src/noise/crypto_resolver.rs b/comms/core/src/noise/crypto_resolver.rs index e7f1417084..27490983f3 100644 --- a/comms/core/src/noise/crypto_resolver.rs +++ b/comms/core/src/noise/crypto_resolver.rs @@ -101,7 +101,7 @@ impl Dh for CommsDiffieHellman { fn set(&mut self, privkey: &[u8]) { // `set` is used in the Builder, so this will panic if given an invalid secret key. - self.secret_key = CommsSecretKey::from_bytes(privkey).expect("invalid secret key"); + self.secret_key = CommsSecretKey::from_canonical_bytes(privkey).expect("invalid secret key"); self.public_key = CommsPublicKey::from_secret_key(&self.secret_key); } @@ -121,7 +121,7 @@ impl Dh for CommsDiffieHellman { } fn dh(&self, public_key: &[u8], out: &mut [u8]) -> Result<(), snow::Error> { - let pk = CommsPublicKey::from_bytes(&public_key[..self.pub_len()]).map_err(|_| snow::Error::Dh)?; + let pk = CommsPublicKey::from_canonical_bytes(&public_key[..self.pub_len()]).map_err(|_| snow::Error::Dh)?; let shared = CommsDHKE::new(&self.secret_key, &pk); let hash = noise_kdf(&shared); copy_slice!(hash.reveal(), out); @@ -146,9 +146,9 @@ mod test { fn generate() { let keypair = build_keypair(); - let sk = CommsSecretKey::from_bytes(&keypair.private).unwrap(); + let sk = CommsSecretKey::from_canonical_bytes(&keypair.private).unwrap(); let expected_pk = CommsPublicKey::from_secret_key(&sk); - let pk = CommsPublicKey::from_bytes(&keypair.public).unwrap(); + let pk = CommsPublicKey::from_canonical_bytes(&keypair.public).unwrap(); assert_eq!(pk, expected_pk); } diff --git a/comms/core/src/noise/socket.rs b/comms/core/src/noise/socket.rs index 6e4b1bcfa5..fefeb50fcd 100644 --- a/comms/core/src/noise/socket.rs +++ b/comms/core/src/noise/socket.rs @@ -160,7 +160,7 @@ impl NoiseSocket { /// Get the remote static key as a CommsPublicKey pub fn get_remote_public_key(&self) -> Option { self.get_remote_static() - .and_then(|s| CommsPublicKey::from_bytes(s).ok()) + .and_then(|s| CommsPublicKey::from_canonical_bytes(s).ok()) } } diff --git a/comms/core/src/peer_manager/identity_signature.rs b/comms/core/src/peer_manager/identity_signature.rs index 616ccb3c0e..ab04e5bb4b 100644 --- a/comms/core/src/peer_manager/identity_signature.rs +++ b/comms/core/src/peer_manager/identity_signature.rs @@ -22,7 +22,9 @@ use std::convert::{TryFrom, TryInto}; +use blake2::Blake2b; use chrono::{DateTime, NaiveDateTime, Utc}; +use digest::consts::U64; use prost::Message; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; @@ -35,7 +37,7 @@ use crate::{ multiaddr::Multiaddr, peer_manager::{PeerFeatures, PeerManagerError}, proto, - types::{CommsChallenge, CommsPublicKey, CommsSecretKey, Signature}, + types::{CommsPublicKey, CommsSecretKey, Signature}, }; /// Signature that secures the peer identity @@ -75,7 +77,7 @@ impl IdentitySignature { updated_at, ) .finalize(); - let signature = Signature::sign_raw(secret_key, secret_nonce, challenge.as_ref()) + let signature = Signature::sign_raw_wide(secret_key, secret_nonce, challenge.as_ref()) .expect("unreachable panic: challenge hash digest is the correct length"); Self { version: Self::LATEST_VERSION, @@ -120,7 +122,7 @@ impl IdentitySignature { self.updated_at, ) .finalize(); - self.signature.verify_challenge(public_key, challenge.as_ref()) + self.signature.verify_raw_wide(public_key, challenge.as_ref()) } fn construct_challenge<'a, I: IntoIterator>( @@ -130,9 +132,9 @@ impl IdentitySignature { features: PeerFeatures, addresses: I, updated_at: DateTime, - ) -> DomainSeparatedHasher { + ) -> DomainSeparatedHasher, CommsCorePeerManagerDomain> { // e = H(P||R||m) - let challenge = comms_core_peer_manager_domain::(IDENTITY_SIGNATURE) + let challenge = comms_core_peer_manager_domain::>(IDENTITY_SIGNATURE) .chain(public_key.as_bytes()) .chain(public_nonce.as_bytes()) .chain(version.to_le_bytes()) @@ -160,10 +162,10 @@ impl TryFrom for IdentitySignature { fn try_from(value: proto::identity::IdentitySignature) -> Result { let version = u8::try_from(value.version).map_err(|_| PeerManagerError::InvalidIdentitySignature)?; - let public_nonce = - CommsPublicKey::from_bytes(&value.public_nonce).map_err(|_| PeerManagerError::InvalidIdentitySignature)?; - let signature = - CommsSecretKey::from_bytes(&value.signature).map_err(|_| PeerManagerError::InvalidIdentitySignature)?; + let public_nonce = CommsPublicKey::from_canonical_bytes(&value.public_nonce) + .map_err(|_| PeerManagerError::InvalidIdentitySignature)?; + let signature = CommsSecretKey::from_canonical_bytes(&value.signature) + .map_err(|_| PeerManagerError::InvalidIdentitySignature)?; let updated_at = NaiveDateTime::from_timestamp_opt(value.updated_at, 0).ok_or(PeerManagerError::InvalidIdentitySignature)?; let updated_at = DateTime::::from_utc(updated_at, Utc); diff --git a/comms/core/src/peer_manager/node_id.rs b/comms/core/src/peer_manager/node_id.rs index 9af7a8384f..49b4623754 100644 --- a/comms/core/src/peer_manager/node_id.rs +++ b/comms/core/src/peer_manager/node_id.rs @@ -137,7 +137,7 @@ impl NodeId { impl ByteArray for NodeId { /// Try and convert the given byte array to a NodeId. Any failures (incorrect array length, /// implementation-specific checks, etc) return a [ByteArrayError](enum.ByteArrayError.html). - fn from_bytes(bytes: &[u8]) -> Result { + fn from_canonical_bytes(bytes: &[u8]) -> Result { bytes.try_into().map_err(|err| ByteArrayError::ConversionError { reason: format!("{:?}", err), }) @@ -152,7 +152,7 @@ impl ByteArray for NodeId { impl ByteArray for Box { /// Try and convert the given byte array to a NodeId. Any failures (incorrect array length, /// implementation-specific checks, etc) return a [ByteArrayError](enum.ByteArrayError.html). - fn from_bytes(bytes: &[u8]) -> Result { + fn from_canonical_bytes(bytes: &[u8]) -> Result { let node_id = NodeId::try_from(bytes).map_err(|err| ByteArrayError::ConversionError { reason: format!("{:?}", err), })?; diff --git a/comms/core/src/types.rs b/comms/core/src/types.rs index 6ebe254ff5..748eb0ffd7 100644 --- a/comms/core/src/types.rs +++ b/comms/core/src/types.rs @@ -22,8 +22,6 @@ //! Common Tari comms types -use blake2::Blake2b; -use digest::consts::U32; use tari_crypto::{ dhke::DiffieHellmanSharedSecret, hash_domain, @@ -46,8 +44,6 @@ pub type CommsSecretKey = ::K; // Diffie-Hellman key exchange type pub type CommsDHKE = DiffieHellmanSharedSecret; -/// Specify the digest type for the signature challenges -pub type CommsChallenge = Blake2b; /// Comms signature type pub type Signature = SchnorrSignature; diff --git a/comms/dht/Cargo.toml b/comms/dht/Cargo.toml index e7f0fae427..54cbaec626 100644 --- a/comms/dht/Cargo.toml +++ b/comms/dht/Cargo.toml @@ -21,6 +21,7 @@ tari_common_sqlite = { path = "../../common_sqlite" } anyhow = "1.0.53" bitflags = "1" +blake2 = "0.10" chacha20 = "0.7.1" chacha20poly1305 = "0.10.1" chrono = { version = "0.4.19", default-features = false } diff --git a/comms/dht/src/crypt.rs b/comms/dht/src/crypt.rs index 9e719b59db..3c9a97b8b4 100644 --- a/comms/dht/src/crypt.rs +++ b/comms/dht/src/crypt.rs @@ -30,7 +30,10 @@ use tari_comms::{ types::{CommsDHKE, CommsPublicKey, CommsSecretKey}, BufMut, }; -use tari_crypto::tari_utilities::{epoch_time::EpochTime, ByteArray}; +use tari_crypto::{ + keys::SecretKey, + tari_utilities::{epoch_time::EpochTime, ByteArray}, +}; use tari_utilities::{hidden_type, safe_array::SafeArray, ByteArrayError, Hidden}; use zeroize::Zeroize; @@ -46,9 +49,9 @@ use crate::{ // `ChaCha20` key used to encrypt messages hidden_type!(CommsMessageKey, SafeArray() }>); -// Mask used (as a secret key) for sender key offset; we fix it to 32 bytes for compatibility -// This isn't fully generic, but will work for 32-byte hashers and byte-to-scalar functionality -hidden_type!(CommsKeyMask, SafeArray); +// Mask used (as a secret key) for sender key offset; we fix it to 64 bytes for wide reduction +// Note that this is not fully generic! +hidden_type!(CommsKeyMask, SafeArray); const MESSAGE_BASE_LENGTH: usize = 6000; @@ -141,8 +144,7 @@ pub fn generate_key_mask(data: &CommsDHKE) -> Result [u8; 32] { } pub fn create_message_hash(message_signature: &[u8], body: &[u8]) -> [u8; 32] { - let result = comms_dht_dedup_message_hash::(DEDUP_MESSAGE_HASH_LABEL) + let result = comms_dht_dedup_message_hash::>(DEDUP_MESSAGE_HASH_LABEL) .chain(message_signature) .chain(body) .finalize(); diff --git a/comms/dht/src/envelope.rs b/comms/dht/src/envelope.rs index 28c87e5be1..db72b1fcd9 100644 --- a/comms/dht/src/envelope.rs +++ b/comms/dht/src/envelope.rs @@ -224,7 +224,7 @@ impl TryFrom for DhtMessageHeader { None } else { Some( - CommsPublicKey::from_bytes(&header.ephemeral_public_key) + CommsPublicKey::from_canonical_bytes(&header.ephemeral_public_key) .map_err(|_| DhtMessageError::InvalidEphemeralPublicKey)?, ) }; @@ -368,7 +368,7 @@ impl TryFrom for NodeDestination { match destination { Destination::Unknown(_) => Ok(NodeDestination::Unknown), Destination::PublicKey(pk) => { - CommsPublicKey::from_bytes(&pk).map(|pk| NodeDestination::PublicKey(Box::new(pk))) + CommsPublicKey::from_canonical_bytes(&pk).map(|pk| NodeDestination::PublicKey(Box::new(pk))) }, } } diff --git a/comms/dht/src/lib.rs b/comms/dht/src/lib.rs index 5967ad233e..024081fa82 100644 --- a/comms/dht/src/lib.rs +++ b/comms/dht/src/lib.rs @@ -122,23 +122,28 @@ pub mod inbound; pub mod outbound; pub mod store_forward; -use tari_comms::types::CommsChallenge; +use blake2::Blake2b; +use digest::consts::{U32, U64}; use tari_crypto::{hash_domain, hashing::DomainSeparatedHasher}; hash_domain!(DHTCommsHashDomain, "com.tari.comms.dht"); -pub fn comms_dht_hash_domain_challenge() -> DomainSeparatedHasher { - DomainSeparatedHasher::::new_with_label("challenge") +/// Hash domain used to produce binding message hashes +pub fn comms_dht_hash_domain_challenge() -> DomainSeparatedHasher, DHTCommsHashDomain> { + DomainSeparatedHasher::, DHTCommsHashDomain>::new_with_label("challenge") } -pub fn comms_dht_hash_domain_key_message() -> DomainSeparatedHasher { - DomainSeparatedHasher::::new_with_label("key_message") +/// Hash domain used for message encryption keys +pub fn comms_dht_hash_domain_key_message() -> DomainSeparatedHasher, DHTCommsHashDomain> { + DomainSeparatedHasher::, DHTCommsHashDomain>::new_with_label("key_message") } -pub fn comms_dht_hash_domain_key_mask() -> DomainSeparatedHasher { - DomainSeparatedHasher::::new_with_label("key_mask") +/// Hash domain used for message encryption key masking +pub fn comms_dht_hash_domain_key_mask() -> DomainSeparatedHasher, DHTCommsHashDomain> { + DomainSeparatedHasher::, DHTCommsHashDomain>::new_with_label("key_mask") } -pub fn comms_dht_hash_domain_message_signature() -> DomainSeparatedHasher { - DomainSeparatedHasher::::new_with_label("message_signature") +/// Hash domain used for message signing +pub fn comms_dht_hash_domain_message_signature() -> DomainSeparatedHasher, DHTCommsHashDomain> { + DomainSeparatedHasher::, DHTCommsHashDomain>::new_with_label("message_signature") } diff --git a/comms/dht/src/message_signature.rs b/comms/dht/src/message_signature.rs index fa71033e93..d95c07d3c8 100644 --- a/comms/dht/src/message_signature.rs +++ b/comms/dht/src/message_signature.rs @@ -39,7 +39,7 @@ fn construct_message_signature_hash( signer_public_key: &CommsPublicKey, public_nonce: &CommsPublicKey, message: &[u8], -) -> [u8; 32] { +) -> [u8; 64] { // produce domain separated hash of input data, in such a way that e = H_mac(P||R||m) let domain_separated_hash = comms_dht_hash_domain_message_signature() .chain(signer_public_key.as_bytes()) @@ -47,7 +47,7 @@ fn construct_message_signature_hash( .chain(message) .finalize(); - let mut output = [0u8; 32]; + let mut output = [0u8; 64]; output.copy_from_slice(domain_separated_hash.as_ref()); output @@ -59,7 +59,7 @@ impl MessageSignature { let (nonce_s, nonce_pk) = CommsPublicKey::random_keypair(&mut OsRng); let signer_public_key = CommsPublicKey::from_secret_key(&signer_secret_key); let challenge = construct_message_signature_hash(&signer_public_key, &nonce_pk, message); - let signature = Signature::sign_raw(&signer_secret_key, nonce_s, &challenge) + let signature = Signature::sign_raw_wide(&signer_secret_key, nonce_s, &challenge) .expect("challenge is [u8;32] but SchnorrSignature::sign failed"); Self { @@ -72,7 +72,7 @@ impl MessageSignature { pub fn verify(&self, message: &[u8]) -> bool { let challenge = construct_message_signature_hash(&self.signer_public_key, self.signature.get_public_nonce(), message); - self.signature.verify_challenge(&self.signer_public_key, &challenge) + self.signature.verify_raw_wide(&self.signer_public_key, &challenge) } /// Consume this instance, returning the public key of the signer. @@ -94,13 +94,13 @@ impl TryFrom for MessageSignature { type Error = MessageSignatureError; fn try_from(message_signature: ProtoMessageSignature) -> Result { - let signer_public_key = CommsPublicKey::from_bytes(&message_signature.signer_public_key) + let signer_public_key = CommsPublicKey::from_canonical_bytes(&message_signature.signer_public_key) .map_err(|_| MessageSignatureError::InvalidSignerPublicKeyBytes)?; - let public_nonce = CommsPublicKey::from_bytes(&message_signature.public_nonce) + let public_nonce = CommsPublicKey::from_canonical_bytes(&message_signature.public_nonce) .map_err(|_| MessageSignatureError::InvalidPublicNonceBytes)?; - let signature = CommsSecretKey::from_bytes(&message_signature.signature) + let signature = CommsSecretKey::from_canonical_bytes(&message_signature.signature) .map_err(|_| MessageSignatureError::InvalidSignatureBytes)?; Ok(Self { @@ -157,7 +157,7 @@ mod test { let (mut mac, signer_k) = setup(); let signer_pk = CommsPublicKey::from_secret_key(&signer_k); let msg = construct_message_signature_hash(&signer_pk, mac.signature.get_public_nonce(), MSG); - let msg_scalar = CommsSecretKey::from_bytes(&msg).unwrap(); + let msg_scalar = CommsSecretKey::from_bytes_wide(&msg).unwrap(); // Some `a` key let (bad_signer_k, bad_signer_pk) = CommsPublicKey::random_keypair(&mut OsRng); @@ -181,7 +181,7 @@ mod test { // Change to . Note: We need signer_k because the Signature interface does not provide a way to // change just the public nonce, an attacker does not need the secret key. - mac.signature = Signature::sign_raw(&signer_k, nonce_k, &msg).unwrap(); + mac.signature = Signature::sign_raw_wide(&signer_k, nonce_k, &msg).unwrap(); assert!(!mac.verify(MSG)); } } diff --git a/comms/dht/src/peer_validator.rs b/comms/dht/src/peer_validator.rs index 5613607845..427ba73de4 100644 --- a/comms/dht/src/peer_validator.rs +++ b/comms/dht/src/peer_validator.rs @@ -147,8 +147,8 @@ mod tests { signature: IdentitySignature::new( 0, Signature::new( - RistrettoPublicKey::from_bytes(&[0u8; 32]).unwrap(), - RistrettoSecretKey::from_bytes(&[0u8; 32]).unwrap(), + RistrettoPublicKey::from_canonical_bytes(&[0u8; 32]).unwrap(), + RistrettoSecretKey::from_canonical_bytes(&[0u8; 32]).unwrap(), ), Default::default(), ), diff --git a/comms/dht/src/proto/mod.rs b/comms/dht/src/proto/mod.rs index 719081b34f..9f7c35c419 100644 --- a/comms/dht/src/proto/mod.rs +++ b/comms/dht/src/proto/mod.rs @@ -115,8 +115,8 @@ impl TryFrom for UnvalidatedPeerInfo { type Error = anyhow::Error; fn try_from(value: rpc::PeerInfo) -> Result { - let public_key = - CommsPublicKey::from_bytes(&value.public_key).map_err(|e| anyhow!("PeerInfo invalid public key: {}", e))?; + let public_key = CommsPublicKey::from_canonical_bytes(&value.public_key) + .map_err(|e| anyhow!("PeerInfo invalid public key: {}", e))?; let claims = value .claims .into_iter() @@ -156,10 +156,10 @@ impl TryFrom for IdentitySignature { fn try_from(value: common::IdentitySignature) -> Result { let version = u8::try_from(value.version) .map_err(|_| anyhow::anyhow!("Invalid peer identity signature version {}", value.version))?; - let public_nonce = - CommsPublicKey::from_bytes(&value.public_nonce).map_err(|e| anyhow!("Invalid public nonce: {}", e))?; + let public_nonce = CommsPublicKey::from_canonical_bytes(&value.public_nonce) + .map_err(|e| anyhow!("Invalid public nonce: {}", e))?; let signature = - CommsSecretKey::from_bytes(&value.signature).map_err(|e| anyhow!("Invalid signature: {}", e))?; + CommsSecretKey::from_canonical_bytes(&value.signature).map_err(|e| anyhow!("Invalid signature: {}", e))?; let updated_at = NaiveDateTime::from_timestamp_opt(value.updated_at, 0) .ok_or_else(|| anyhow::anyhow!("updated_at overflowed"))?; let updated_at = DateTime::::from_utc(updated_at, Utc); diff --git a/comms/dht/src/rpc/peer_info.rs b/comms/dht/src/rpc/peer_info.rs index 668596f75e..bbd8eab896 100644 --- a/comms/dht/src/rpc/peer_info.rs +++ b/comms/dht/src/rpc/peer_info.rs @@ -72,7 +72,7 @@ impl TryFrom for UnvalidatedPeerInfo { type Error = anyhow::Error; fn try_from(value: DiscoveryMessage) -> Result { - let public_key = RistrettoPublicKey::from_bytes(&value.public_key) + let public_key = RistrettoPublicKey::from_canonical_bytes(&value.public_key) .map_err(|e| anyhow!("DiscoveryMessage invalid public key: {}", e))?; let features = PeerFeatures::from_bits(value.peer_features) @@ -103,7 +103,7 @@ impl TryFrom for UnvalidatedPeerInfo { type Error = anyhow::Error; fn try_from(value: DiscoveryResponseMessage) -> Result { - let public_key = RistrettoPublicKey::from_bytes(&value.public_key) + let public_key = RistrettoPublicKey::from_canonical_bytes(&value.public_key) .map_err(|e| anyhow!("DiscoveryMessage invalid public key: {}", e))?; let features = PeerFeatures::from_bits(value.peer_features) @@ -135,7 +135,7 @@ impl TryFrom for UnvalidatedPeerInfo { type Error = anyhow::Error; fn try_from(value: JoinMessage) -> Result { - let public_key = RistrettoPublicKey::from_bytes(&value.public_key) + let public_key = RistrettoPublicKey::from_canonical_bytes(&value.public_key) .map_err(|e| anyhow!("JoinMessage invalid public key: {}", e))?; let features = PeerFeatures::from_bits(value.peer_features) diff --git a/comms/dht/src/rpc/service.rs b/comms/dht/src/rpc/service.rs index 55c2c653f3..e0ac04f21d 100644 --- a/comms/dht/src/rpc/service.rs +++ b/comms/dht/src/rpc/service.rs @@ -127,7 +127,7 @@ impl DhtRpcService for DhtRpcServiceImpl { let node_id = if message.closer_to.is_empty() { request.context().peer_node_id().clone() } else { - NodeId::from_bytes(&message.closer_to) + NodeId::from_canonical_bytes(&message.closer_to) .map_err(|_| RpcStatus::bad_request("`closer_to` did not contain a valid NodeId"))? }; @@ -141,7 +141,7 @@ impl DhtRpcService for DhtRpcServiceImpl { let mut excluded = message .excluded .iter() - .filter_map(|node_id| NodeId::from_bytes(node_id).ok()) + .filter_map(|node_id| NodeId::from_canonical_bytes(node_id).ok()) .collect::>(); if excluded.len() != message.excluded.len() { diff --git a/infrastructure/tari_script/src/op_codes.rs b/infrastructure/tari_script/src/op_codes.rs index b12f813b87..895bea560a 100644 --- a/infrastructure/tari_script/src/op_codes.rs +++ b/infrastructure/tari_script/src/op_codes.rs @@ -72,7 +72,7 @@ pub fn slice_to_vec_pubkeys(slice: &[u8], num: usize) -> Result, ByteArrayError>>()?; Ok(public_keys) @@ -373,7 +373,7 @@ impl Opcode { if bytes.len() < 33 { return Err(ScriptError::InvalidData); } - let p = RistrettoPublicKey::from_bytes(&bytes[1..33])?; + let p = RistrettoPublicKey::from_canonical_bytes(&bytes[1..33])?; Ok((PushPubKey(Box::new(p)), &bytes[33..])) }, OP_DROP => Ok((Drop, &bytes[1..])), diff --git a/infrastructure/tari_script/src/script.rs b/infrastructure/tari_script/src/script.rs index 39ba01dc53..be49e68722 100644 --- a/infrastructure/tari_script/src/script.rs +++ b/infrastructure/tari_script/src/script.rs @@ -20,12 +20,15 @@ use std::{cmp::Ordering, collections::HashSet, convert::TryFrom, fmt, io, ops::D use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; -use digest::{consts::U32, Digest}; +use digest::{ + consts::{U32, U64}, + Digest, +}; use integer_encoding::{VarIntReader, VarIntWriter}; use sha2::Sha256; use sha3::Sha3_256; use tari_crypto::{ - keys::PublicKey, + keys::{PublicKey, SecretKey}, ristretto::{RistrettoPublicKey, RistrettoSchnorr, RistrettoSecretKey}, }; use tari_utilities::{ @@ -238,11 +241,11 @@ impl TariScript { /// Calculate the message hash that CHECKSIG uses to verify signatures pub fn script_message(&self, pub_key: &RistrettoPublicKey) -> Result { - let b = Blake2b::::default() + let b = Blake2b::::default() .chain_update(pub_key.as_bytes()) .chain_update(self.to_bytes()) .finalize(); - RistrettoSecretKey::from_bytes(b.as_slice()).map_err(|_| ScriptError::InvalidSignature) + RistrettoSecretKey::from_bytes_wide(b.as_slice()).map_err(|_| ScriptError::InvalidSignature) } // pending updates to Dalek/Digest @@ -562,7 +565,7 @@ impl TariScript { let pk = stack.pop().ok_or(ScriptError::StackUnderflow)?; let sig = stack.pop().ok_or(ScriptError::StackUnderflow)?; match (pk, sig) { - (PublicKey(p), Signature(s)) => Ok(s.verify_challenge(&p, &message)), + (PublicKey(p), Signature(s)) => Ok(s.verify_raw_canonical(&p, &message)), (..) => Err(ScriptError::IncompatibleTypes), } } @@ -614,7 +617,7 @@ impl TariScript { // Check every signature against each public key looking for a valid signature for s in &signatures { for (i, pk) in public_keys.iter().enumerate() { - if !sig_set.contains(s) && !key_signed[i] && s.verify_challenge(pk, &message) { + if !sig_set.contains(s) && !key_signed[i] && s.verify_raw_canonical(pk, &message) { // This prevents Alice creating 2 different sigs against her public key key_signed[i] = true; sig_set.insert(s); @@ -637,11 +640,11 @@ impl TariScript { fn handle_to_ristretto_point(&self, stack: &mut ExecutionStack) -> Result<(), ScriptError> { let item = stack.pop().ok_or(ScriptError::StackUnderflow)?; let scalar = match &item { - StackItem::Hash(hash) => hash.as_slice(), + StackItem::Hash(hash) => hash.as_slice(), // TODO: confirm this isn't problematic StackItem::Scalar(scalar) => scalar.as_slice(), _ => return Err(ScriptError::IncompatibleTypes), }; - let ristretto_sk = RistrettoSecretKey::from_bytes(scalar).map_err(|_| ScriptError::InvalidData)?; + let ristretto_sk = RistrettoSecretKey::from_canonical_bytes(scalar).map_err(|_| ScriptError::InvalidData)?; let ristretto_pk = RistrettoPublicKey::from_secret_key(&ristretto_sk); stack.push(StackItem::PublicKey(ristretto_pk))?; Ok(()) @@ -1068,7 +1071,7 @@ mod test { let (pvt_key, pub_key) = RistrettoPublicKey::random_keypair(&mut rng); let nonce = RistrettoSecretKey::random(&mut rng); let m_key = RistrettoSecretKey::random(&mut rng); - let sig = RistrettoSchnorr::sign_raw(&pvt_key, nonce, m_key.as_bytes()).unwrap(); + let sig = RistrettoSchnorr::sign_raw_canonical(&pvt_key, nonce, m_key.as_bytes()).unwrap(); let msg = slice_to_boxed_message(m_key.as_bytes()); let script = script!(CheckSig(msg)); let inputs = inputs!(sig.clone(), pub_key.clone()); @@ -1090,7 +1093,7 @@ mod test { let (pvt_key, pub_key) = RistrettoPublicKey::random_keypair(&mut rng); let nonce = RistrettoSecretKey::random(&mut rng); let m_key = RistrettoSecretKey::random(&mut rng); - let sig = RistrettoSchnorr::sign_raw(&pvt_key, nonce, m_key.as_bytes()).unwrap(); + let sig = RistrettoSchnorr::sign_raw_canonical(&pvt_key, nonce, m_key.as_bytes()).unwrap(); let msg = slice_to_boxed_message(m_key.as_bytes()); let script = script!(CheckSigVerify(msg) PushOne); let inputs = inputs!(sig.clone(), pub_key.clone()); @@ -1119,7 +1122,7 @@ mod test { for _ in 0..n { let (k, p) = RistrettoPublicKey::random_keypair(&mut rng); let r = RistrettoSecretKey::random(&mut rng); - let s = RistrettoSchnorr::sign_raw(&k, r, m.as_bytes()).unwrap(); + let s = RistrettoSchnorr::sign_raw_canonical(&k, r, m.as_bytes()).unwrap(); data.push((k, p, s)); } @@ -1141,11 +1144,11 @@ mod test { let r4 = RistrettoSecretKey::random(&mut rng); let r5 = RistrettoSecretKey::random(&mut rng); let m = RistrettoSecretKey::random(&mut rng); - let s_alice = RistrettoSchnorr::sign_raw(&k_alice, r1, m.as_bytes()).unwrap(); - let s_bob = RistrettoSchnorr::sign_raw(&k_bob, r2, m.as_bytes()).unwrap(); - let s_eve = RistrettoSchnorr::sign_raw(&k_eve, r3, m.as_bytes()).unwrap(); - let s_carol = RistrettoSchnorr::sign_raw(&k_carol, r4, m.as_bytes()).unwrap(); - let s_alice2 = RistrettoSchnorr::sign_raw(&k_alice, r5, m.as_bytes()).unwrap(); + let s_alice = RistrettoSchnorr::sign_raw_canonical(&k_alice, r1, m.as_bytes()).unwrap(); + let s_bob = RistrettoSchnorr::sign_raw_canonical(&k_bob, r2, m.as_bytes()).unwrap(); + let s_eve = RistrettoSchnorr::sign_raw_canonical(&k_eve, r3, m.as_bytes()).unwrap(); + let s_carol = RistrettoSchnorr::sign_raw_canonical(&k_carol, r4, m.as_bytes()).unwrap(); + let s_alice2 = RistrettoSchnorr::sign_raw_canonical(&k_alice, r5, m.as_bytes()).unwrap(); let msg = slice_to_boxed_message(m.as_bytes()); // 1 of 2 @@ -1330,10 +1333,10 @@ mod test { let r3 = RistrettoSecretKey::random(&mut rng); let r4 = RistrettoSecretKey::random(&mut rng); let m = RistrettoSecretKey::random(&mut rng); - let s_alice = RistrettoSchnorr::sign_raw(&k_alice, r1, m.as_bytes()).unwrap(); - let s_bob = RistrettoSchnorr::sign_raw(&k_bob, r2, m.as_bytes()).unwrap(); - let s_eve = RistrettoSchnorr::sign_raw(&k_eve, r3, m.as_bytes()).unwrap(); - let s_carol = RistrettoSchnorr::sign_raw(&k_carol, r4, m.as_bytes()).unwrap(); + let s_alice = RistrettoSchnorr::sign_raw_canonical(&k_alice, r1, m.as_bytes()).unwrap(); + let s_bob = RistrettoSchnorr::sign_raw_canonical(&k_bob, r2, m.as_bytes()).unwrap(); + let s_eve = RistrettoSchnorr::sign_raw_canonical(&k_eve, r3, m.as_bytes()).unwrap(); + let s_carol = RistrettoSchnorr::sign_raw_canonical(&k_carol, r4, m.as_bytes()).unwrap(); let msg = slice_to_boxed_message(m.as_bytes()); // 1 of 2 @@ -1512,8 +1515,8 @@ mod test { let msg = slice_to_boxed_message(m.as_bytes()); let script = script!(Add RevRot Add CheckSigVerify(msg) PushOne); - let s1 = RistrettoSchnorr::sign_raw(&k1, r1, m.as_bytes()).unwrap(); - let s2 = RistrettoSchnorr::sign_raw(&k2, r2, m.as_bytes()).unwrap(); + let s1 = RistrettoSchnorr::sign_raw_canonical(&k1, r1, m.as_bytes()).unwrap(); + let s2 = RistrettoSchnorr::sign_raw_canonical(&k2, r2, m.as_bytes()).unwrap(); let inputs = inputs!(p1, p2, s1, s2); let result = script.execute(&inputs).unwrap(); assert_eq!(result, Number(1)); @@ -1647,9 +1650,9 @@ mod test { let m = RistrettoSecretKey::random(&mut rng); let msg = slice_to_boxed_message(m.as_bytes()); - let s_alice = RistrettoSchnorr::sign_raw(&k_alice, r1, m.as_bytes()).unwrap(); - let s_bob = RistrettoSchnorr::sign_raw(&k_bob, r2, m.as_bytes()).unwrap(); - let s_eve = RistrettoSchnorr::sign_raw(&k_eve, r3, m.as_bytes()).unwrap(); + let s_alice = RistrettoSchnorr::sign_raw_canonical(&k_alice, r1, m.as_bytes()).unwrap(); + let s_bob = RistrettoSchnorr::sign_raw_canonical(&k_bob, r2, m.as_bytes()).unwrap(); + let s_eve = RistrettoSchnorr::sign_raw_canonical(&k_eve, r3, m.as_bytes()).unwrap(); // 1 of 2 use crate::Opcode::{CheckSig, Drop, Dup, Else, EndIf, IfThen, PushPubKey, Return}; diff --git a/infrastructure/tari_script/src/stack.rs b/infrastructure/tari_script/src/stack.rs index 94902398cd..ded78b7857 100644 --- a/infrastructure/tari_script/src/stack.rs +++ b/infrastructure/tari_script/src/stack.rs @@ -150,7 +150,7 @@ impl StackItem { if b.len() < 32 { return None; } - let c = PedersenCommitment::from_bytes(&b[..32]).ok()?; + let c = PedersenCommitment::from_canonical_bytes(&b[..32]).ok()?; Some((StackItem::Commitment(c), &b[32..])) } @@ -158,7 +158,7 @@ impl StackItem { if b.len() < 32 { return None; } - let p = RistrettoPublicKey::from_bytes(&b[..32]).ok()?; + let p = RistrettoPublicKey::from_canonical_bytes(&b[..32]).ok()?; Some((StackItem::PublicKey(p), &b[32..])) } @@ -166,8 +166,8 @@ impl StackItem { if b.len() < 64 { return None; } - let r = RistrettoPublicKey::from_bytes(&b[..32]).ok()?; - let s = RistrettoSecretKey::from_bytes(&b[32..64]).ok()?; + let r = RistrettoPublicKey::from_canonical_bytes(&b[..32]).ok()?; + let s = RistrettoSecretKey::from_canonical_bytes(&b[32..64]).ok()?; let sig = RistrettoSchnorr::new(r, s); Some((StackItem::Signature(sig), &b[64..])) } @@ -391,7 +391,10 @@ fn counter(values: [u8; 6], item: &StackItem) -> [u8; 6] { mod test { use blake2::Blake2b; use borsh::{BorshDeserialize, BorshSerialize}; - use digest::{consts::U32, Digest}; + use digest::{ + consts::{U32, U64}, + Digest, + }; use rand::rngs::OsRng; use tari_crypto::{ keys::{PublicKey, SecretKey}, @@ -400,6 +403,7 @@ mod test { use tari_utilities::{ hex::{from_hex, Hex}, message_format::MessageFormat, + ByteArray, }; use crate::{op_codes::ScalarValue, ExecutionStack, HashValue, StackItem}; @@ -409,7 +413,7 @@ mod test { use crate::StackItem::{Number, PublicKey, Signature}; let k = RistrettoSecretKey::random(&mut rand::thread_rng()); let p = RistrettoPublicKey::from_secret_key(&k); - let s = RistrettoSchnorr::sign_message(&k, b"hi", &mut OsRng).unwrap(); + let s = RistrettoSchnorr::sign(&k, b"hi", &mut OsRng).unwrap(); let items = vec![Number(5432), Number(21), Signature(s), PublicKey(p)]; let stack = ExecutionStack::new(items); let bytes = stack.to_bytes(); @@ -424,11 +428,12 @@ mod test { let r = RistrettoSecretKey::from_hex("193ee873f3de511eda8ae387db6498f3d194d31a130a94cdf13dc5890ec1ad0f").unwrap(); let p = RistrettoPublicKey::from_secret_key(&k); - let m = Blake2b::::digest(b"Hello Tari Script"); - let sig = RistrettoSchnorr::sign_raw(&k, r, m.as_slice()).unwrap(); - let scalar: ScalarValue = m.into(); + let m = RistrettoSecretKey::from_bytes_wide(&Blake2b::::digest(b"Hello Tari Script")).unwrap(); + let sig = RistrettoSchnorr::sign_raw_canonical(&k, r, m.as_bytes()).unwrap(); + let mut scalar: ScalarValue = [0u8; 32]; + scalar.copy_from_slice(m.as_bytes()); let inputs = inputs!(sig, p, scalar); - assert_eq!(inputs.to_hex(), "0500f7c695528c858cde76dab3076908e01228b6dbdd5f671bed1b03b89e170c316db1023d5c46d78a97da8eb6c5a37e00d5f2fee182dcb38c1b6c65e90a43c1090456c0fa32558d6edc0916baa26b48e745de834571534ca253ea82435f08ebbc7c06fdf9fc345d2cdd8aff624a55f824c7c9ce3cc972e011b4e750e417a90ecc5da5"); + assert_eq!(inputs.to_hex(), "0500f7c695528c858cde76dab3076908e01228b6dbdd5f671bed1b03b89e170c315c4a28c0202dec8769e7a6cc5b407e90664ce73c57404ab9c288bfe6a72d0d090456c0fa32558d6edc0916baa26b48e745de834571534ca253ea82435f08ebbc7c067c8f42406bb109bfcf5aadf0c72d9324a49b9f4758c83fb2f3364baf562f7d00"); } #[test]