Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ resolver = "2"
[workspace.package]
version = "0.13.1"
edition = "2021"
rust-version = "1.80"
rust-version = "1.85"
authors = [
"Summa <team@summa.one>",
"James Prestwich <james@prestwi.ch>",
Expand All @@ -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"

Expand Down
1 change: 1 addition & 0 deletions crates/bip32/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }

Expand Down
139 changes: 107 additions & 32 deletions crates/bip32/src/derived.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand All @@ -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"),
Expand Down
12 changes: 10 additions & 2 deletions crates/bip32/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down Expand Up @@ -178,4 +185,5 @@ impl From<std::convert::Infallible> for Bip32Error {
mod _silence_warnings {
use gr02 as _;
use gr03 as _;
use gr04 as _;
}
24 changes: 14 additions & 10 deletions crates/bip32/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ macro_rules! inherit_signer {
+ digest::Update
+ digest::HashMarker,
{
fn try_sign_digest(
fn try_sign_digest<F: Fn(&mut D) -> Result<(), k256::ecdsa::Error>>(
&self,
digest: D,
f: F,
) -> Result<k256::ecdsa::Signature, k256::ecdsa::Error> {
self.$attr.try_sign_digest(digest)
self.$attr.try_sign_digest(f)
}
}

Expand All @@ -30,11 +30,11 @@ macro_rules! inherit_signer {
+ digest::Update
+ digest::HashMarker,
{
fn try_sign_digest(
fn try_sign_digest<F: Fn(&mut D) -> 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)
}
}

Expand All @@ -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(())
})
}
}
};
Expand All @@ -75,12 +79,12 @@ macro_rules! inherit_verifier {
where
D: digest::Digest + digest::FixedOutput<OutputSize = k256::elliptic_curve::consts::U32>,
{
fn verify_digest(
fn verify_digest<F: Fn(&mut D) -> 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)
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion crates/bip32/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 23 additions & 7 deletions crates/bip32/src/xkeys.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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]
Expand All @@ -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();
Expand Down
Loading
Loading