diff --git a/Cargo.toml b/Cargo.toml index ca292e4..9aac74b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ resolver = "2" [workspace.package] version = "0.13.1" edition = "2021" -rust-version = "1.80" +rust-version = "1.85" authors = [ "Summa ", "James Prestwich ", @@ -26,22 +26,22 @@ coins-ledger = { path = "crates/ledger", version = "0.13" } base64 = "0.21" bech32 = "0.9" bs58 = "0.5.1" -digest = "0.10.7" -generic-array = "0.14.7" +digest = "0.11" +hybrid-array = "0.4" hex = { package = "const-hex", version = "1.12.0" } -ripemd = "0.1.3" +ripemd = "0.2" serde = "1.0.203" -sha3 = "0.10.8" +sha3 = "0.12" # bip32 -hmac = "0.12.1" -k256 = { version = "0.13", features = ["std", "arithmetic"] } -sha2 = "0.10.8" +hmac = "0.13" +k256 = { version = "0.14", features = ["std", "arithmetic"] } +sha2 = "0.11" thiserror = "1.0.61" # bip39 bitvec = "1.0.1" -pbkdf2 = "0.12.2" +pbkdf2 = "0.13" rand = "0.9.0" once_cell = "1.19.0" diff --git a/crates/bip32/Cargo.toml b/crates/bip32/Cargo.toml index b400af4..81f11b8 100644 --- a/crates/bip32/Cargo.toml +++ b/crates/bip32/Cargo.toml @@ -24,6 +24,7 @@ sha2.workspace = true thiserror.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] +gr04 = { package = "getrandom", version = "0.4", features = ["wasm_js"] } gr03 = { package = "getrandom", version = "0.3", features = ["wasm_js"] } gr02 = { package = "getrandom", version = "0.2", features = ["js"] } diff --git a/crates/bip32/src/derived.rs b/crates/bip32/src/derived.rs index 87fbcff..952bc5c 100644 --- a/crates/bip32/src/derived.rs +++ b/crates/bip32/src/derived.rs @@ -429,19 +429,48 @@ mod test { let key_pub = key.verify_key(); // sign_digest + verify_digest - let sig: Signature = key.sign_digest(digest.clone()); - key_pub.verify_digest(digest.clone(), &sig).unwrap(); + let sig: Signature = key.sign_digest(|d: &mut Hash256| *d = digest.clone()); + key_pub + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) + .unwrap(); - let err_bad_sig = key_pub.verify_digest(wrong_digest.clone(), &sig); + let err_bad_sig = key_pub.verify_digest( + |d: &mut Hash256| { + *d = wrong_digest.clone(); + Ok(()) + }, + &sig, + ); match err_bad_sig { Err(_) => {} _ => panic!("expected signature validation error"), } - let (sig, _): (Signature, RecoveryId) = key.sign_digest(digest.clone()); - key_pub.verify_digest(digest, &sig).unwrap(); + let (sig, _): (Signature, RecoveryId) = + key.sign_digest(|d: &mut Hash256| *d = digest.clone()); + key_pub + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) + .unwrap(); - let err_bad_sig = key_pub.verify_digest(wrong_digest.clone(), &sig); + let err_bad_sig = key_pub.verify_digest( + |d: &mut Hash256| { + *d = wrong_digest.clone(); + Ok(()) + }, + &sig, + ); match err_bad_sig { Err(_) => {} _ => panic!("expected signature validation error"), @@ -468,69 +497,115 @@ mod test { assert_eq!(key.derivation(), &fake_deriv); // sign_digest + verify_digest - let sig: Signature = key.derive_path(&path).unwrap().sign_digest(digest.clone()); + let sig: Signature = key + .derive_path(&path) + .unwrap() + .sign_digest(|d: &mut Hash256| *d = digest.clone()); key_pub .derive_path(&path) .unwrap() - .verify_digest(digest.clone(), &sig) + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) .unwrap(); - let err_bad_sig = key_pub - .derive_path(&path) - .unwrap() - .verify_digest(wrong_digest.clone(), &sig); + let err_bad_sig = key_pub.derive_path(&path).unwrap().verify_digest( + |d: &mut Hash256| { + *d = wrong_digest.clone(); + Ok(()) + }, + &sig, + ); match err_bad_sig { Err(_) => {} _ => panic!("expected signature validation error"), } - let (sig, _): (Signature, RecoveryId) = - key.derive_path(&path).unwrap().sign_digest(digest.clone()); + let (sig, _): (Signature, RecoveryId) = key + .derive_path(&path) + .unwrap() + .sign_digest(|d: &mut Hash256| *d = digest.clone()); key_pub .derive_path(&path) .unwrap() - .verify_digest(digest.clone(), &sig) + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) .unwrap(); - let err_bad_sig = key_pub - .derive_path(&path) - .unwrap() - .verify_digest(wrong_digest.clone(), &sig); + let err_bad_sig = key_pub.derive_path(&path).unwrap().verify_digest( + |d: &mut Hash256| { + *d = wrong_digest.clone(); + Ok(()) + }, + &sig, + ); match err_bad_sig { Err(_) => {} _ => panic!("expected signature validation error"), } // sign + verify - let sig: Signature = key.derive_path(&path).unwrap().sign_digest(digest.clone()); + let sig: Signature = key + .derive_path(&path) + .unwrap() + .sign_digest(|d: &mut Hash256| *d = digest.clone()); key_pub .derive_path(&path) .unwrap() - .verify_digest(digest.clone(), &sig) + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) .unwrap(); - let err_bad_sig = key_pub - .derive_path(&path) - .unwrap() - .verify_digest(wrong_digest.clone(), &sig); + let err_bad_sig = key_pub.derive_path(&path).unwrap().verify_digest( + |d: &mut Hash256| { + *d = wrong_digest.clone(); + Ok(()) + }, + &sig, + ); match err_bad_sig { Err(_) => {} _ => panic!("expected signature validation error"), } // sign_recoverable + verify_recoverable - let (sig, recovery_id): (Signature, RecoveryId) = - key.derive_path(&path).unwrap().sign_digest(digest.clone()); + let (sig, recovery_id): (Signature, RecoveryId) = key + .derive_path(&path) + .unwrap() + .sign_digest(|d: &mut Hash256| *d = digest.clone()); key_pub .derive_path(&path) .unwrap() - .verify_digest(digest, &sig) + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) .unwrap(); - let err_bad_sig = key_pub - .derive_path(&path) - .unwrap() - .verify_digest(wrong_digest.clone(), &sig); + let err_bad_sig = key_pub.derive_path(&path).unwrap().verify_digest( + |d: &mut Hash256| { + *d = wrong_digest.clone(); + Ok(()) + }, + &sig, + ); match err_bad_sig { Err(_) => {} _ => panic!("expected signature validation error"), diff --git a/crates/bip32/src/lib.rs b/crates/bip32/src/lib.rs index 6239a13..90fe94e 100644 --- a/crates/bip32/src/lib.rs +++ b/crates/bip32/src/lib.rs @@ -39,11 +39,18 @@ //! let xpriv: XPriv = xpriv_str.parse().unwrap(); //! //! let child_xpriv = xpriv.derive_child(33)?; -//! let (sig, _recovery_id): (Signature, RecoveryId) = child_xpriv.sign_digest(digest.clone()); +//! let (sig, _recovery_id): (Signature, RecoveryId) = +//! child_xpriv.sign_digest(|d: &mut coins_core::hashes::Hash256| *d = digest.clone()); //! //! // Signing key types are associated with verifying key types. You can always derive a pubkey //! let child_xpub = child_xpriv.verify_key(); -//! child_xpub.verify_digest(digest.clone(), &sig)?; +//! child_xpub.verify_digest( +//! |d: &mut coins_core::hashes::Hash256| { +//! *d = digest.clone(); +//! Ok(()) +//! }, +//! &sig, +//! )?; //! //! MainnetEncoder::xpub_to_base58(&child_xpub)?; //! # Ok(()) @@ -178,4 +185,5 @@ impl From for Bip32Error { mod _silence_warnings { use gr02 as _; use gr03 as _; + use gr04 as _; } diff --git a/crates/bip32/src/macros.rs b/crates/bip32/src/macros.rs index 583360a..42ef90f 100644 --- a/crates/bip32/src/macros.rs +++ b/crates/bip32/src/macros.rs @@ -9,11 +9,11 @@ macro_rules! inherit_signer { + digest::Update + digest::HashMarker, { - fn try_sign_digest( + fn try_sign_digest Result<(), k256::ecdsa::Error>>( &self, - digest: D, + f: F, ) -> Result { - self.$attr.try_sign_digest(digest) + self.$attr.try_sign_digest(f) } } @@ -30,11 +30,11 @@ macro_rules! inherit_signer { + digest::Update + digest::HashMarker, { - fn try_sign_digest( + fn try_sign_digest Result<(), k256::ecdsa::Error>>( &self, - digest: D, + f: F, ) -> Result<(k256::ecdsa::Signature, k256::ecdsa::RecoveryId), k256::ecdsa::Error> { - self.$attr.sign_digest_recoverable(digest) + self.$attr.try_sign_digest(f) } } @@ -53,7 +53,11 @@ macro_rules! inherit_signer { + digest::Update + digest::HashMarker, { - self.$attr.sign_digest_recoverable(digest) + use k256::ecdsa::signature::DigestSigner as _; + self.try_sign_digest(move |d: &mut D| { + *d = digest.clone(); + Ok(()) + }) } } }; @@ -75,12 +79,12 @@ macro_rules! inherit_verifier { where D: digest::Digest + digest::FixedOutput, { - fn verify_digest( + fn verify_digest Result<(), k256::ecdsa::Error>>( &self, - digest: D, + f: F, signature: &k256::ecdsa::Signature, ) -> Result<(), k256::ecdsa::Error> { - self.$attr.verify_digest(digest, signature) + self.$attr.verify_digest(f, signature) } } }; diff --git a/crates/bip32/src/prelude.rs b/crates/bip32/src/prelude.rs index fee4a5d..c911ca0 100644 --- a/crates/bip32/src/prelude.rs +++ b/crates/bip32/src/prelude.rs @@ -15,7 +15,7 @@ pub use k256::{ signature::{DigestSigner as _, DigestVerifier as _}, RecoveryId, Signature, SigningKey, VerifyingKey, }, - elliptic_curve::sec1::ToEncodedPoint as _, + elliptic_curve::sec1::ToSec1Point as _, }; /// shortcut for easy usage diff --git a/crates/bip32/src/xkeys.rs b/crates/bip32/src/xkeys.rs index 5cb0bbe..df4753f 100644 --- a/crates/bip32/src/xkeys.rs +++ b/crates/bip32/src/xkeys.rs @@ -1,6 +1,6 @@ use coins_core::hashes::{Hash160, Hash160Digest, MarkedDigest, MarkedDigestOutput}; -use hmac::{Hmac, Mac}; -use k256::{ecdsa, elliptic_curve::sec1::FromEncodedPoint}; +use hmac::{Hmac, KeyInit, Mac}; +use k256::{ecdsa, elliptic_curve::sec1::FromSec1Point}; use sha2::Sha512; use std::{ convert::{TryFrom, TryInto}, @@ -343,7 +343,7 @@ impl Parent for XPub { } let parent_key = - k256::ProjectivePoint::from_encoded_point(&self.key.to_encoded_point(true)).unwrap(); + k256::ProjectivePoint::from_sec1_point(&self.key.to_sec1_point(true)).unwrap(); let mut tweak_point = k256::ProjectivePoint::GENERATOR.mul(*tweak); tweak_point.add_assign(parent_key); @@ -554,10 +554,18 @@ mod test { let xpriv = MainnetEncoder::xpriv_from_base58(&xpriv_str).unwrap(); let child = xpriv.derive_child(33).unwrap(); - let sig: ecdsa::Signature = child.sign_digest(digest.clone()); + let sig: ecdsa::Signature = child.sign_digest(|d: &mut Hash256| *d = digest.clone()); let child_xpub = child.verify_key(); - child_xpub.verify_digest(digest, &sig).unwrap(); + child_xpub + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) + .unwrap(); } #[test] @@ -570,10 +578,18 @@ mod test { let child = xpriv.derive_child(33).unwrap(); let (sig, recovery_id): (ecdsa::Signature, ecdsa::RecoveryId) = - child.sign_digest(digest.clone()); + child.sign_digest(|d: &mut Hash256| *d = digest.clone()); let child_xpub = child.verify_key(); - child_xpub.verify_digest(digest.clone(), &sig).unwrap(); + child_xpub + .verify_digest( + |d: &mut Hash256| { + *d = digest.clone(); + Ok(()) + }, + &sig, + ) + .unwrap(); let recovered = ecdsa::VerifyingKey::recover_from_digest(digest, &sig, recovery_id).unwrap(); diff --git a/crates/bip39/Cargo.toml b/crates/bip39/Cargo.toml index 075da4d..7a294ac 100644 --- a/crates/bip39/Cargo.toml +++ b/crates/bip39/Cargo.toml @@ -27,6 +27,7 @@ sha2.workspace = true thiserror.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] +gr04 = { package = "getrandom", version = "0.4", features = ["wasm_js"] } gr03 = { package = "getrandom", version = "0.3", features = ["wasm_js"] } gr02 = { package = "getrandom", version = "0.2", features = ["js"] } diff --git a/crates/bip39/src/lib.rs b/crates/bip39/src/lib.rs index 8f88db1..d06b3c8 100644 --- a/crates/bip39/src/lib.rs +++ b/crates/bip39/src/lib.rs @@ -26,4 +26,5 @@ pub use self::wordlist::*; mod _silence_warnings { use gr02 as _; use gr03 as _; + use gr04 as _; } diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 2647b6f..8f5e78d 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -17,7 +17,7 @@ base64.workspace = true bech32.workspace = true bs58 = { workspace = true, features = ["check"] } digest.workspace = true -generic-array.workspace = true +hybrid-array.workspace = true hex.workspace = true ripemd.workspace = true serde = { workspace = true, features = ["derive"] } diff --git a/crates/core/src/hashes.rs b/crates/core/src/hashes.rs index 2b810e2..13d56ff 100644 --- a/crates/core/src/hashes.rs +++ b/crates/core/src/hashes.rs @@ -6,17 +6,12 @@ //! length. use crate::ser::{ByteFormat, SerError, SerResult}; -use digest::{ - core_api::{BlockSizeUser, OutputSizeUser}, - HashMarker, Output, -}; +use digest::{block_api::BlockSizeUser, HashMarker, Output, OutputSizeUser}; use std::io::Write; // Useful re-exports pub use digest::Digest; -#[allow(deprecated)] -// re-exported for API compatibility; generic-array 1.x migration is a breaking change -pub use generic_array::GenericArray; +pub use hybrid_array::Array as GenericArray; pub use ripemd::Ripemd160; pub use sha2::Sha256; pub use sha3::Sha3_256;