Skip to content

Commit 5eeba5a

Browse files
committed
remove use of "hashes" from examples and doccomments
This is a little annoying; the library has a Message type for ECDSA signing which is supposed to be a secure hash digest, but we provide no methods for producing such a digest. So our examples are necessarily a little wonky. Before this commit we would use `bitcoin_hashes` to hash some arbitrary data. This isn't really wise (signing unstructured data or using hashes that aren't domain-separated) but it was shaped similarly to proper usage. Now we just hardcode the "output" of hash functions and convert that. I added some comments to help.
1 parent a2f83da commit 5eeba5a

File tree

4 files changed

+49
-28
lines changed

4 files changed

+49
-28
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ rustdoc-args = ["--cfg", "docsrs"]
1919

2020
[features]
2121
default = ["std"]
22-
std = ["alloc", "secp256k1-sys/std", "rand?/std", "rand?/std_rng", "rand?/thread_rng"
22+
std = ["alloc", "secp256k1-sys/std", "rand?/std", "rand?/std_rng", "rand?/thread_rng" ]
2323
# allow use of Secp256k1::new and related API that requires an allocator
2424
alloc = ["secp256k1-sys/alloc"]
2525
recovery = ["secp256k1-sys/recovery"]

examples/sign_verify.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
extern crate hashes;
1+
//! Signing and Verification Example
2+
//!
3+
//! In this example we directly sign the "output of a hash function"
4+
//! as represented by a 32-byte array. In practice, when signing with
5+
//! the ECDSA API, you should not sign an arbitrary hash like this,
6+
//! whether it is typed as a `[u8; 32]` or a `sha2::Sha256` or whatever.
7+
//!
8+
//! Instead, you should have a dedicated signature hash type, which has
9+
//! constructors ensuring that it represents an (ideally) domain-separated
10+
//! hash of the data you intend to sign. This type should implement
11+
//! `Into<Message>` so it can be passed to `sign_ecdsa` as a message.
12+
//!
13+
//! An example of such a type is `bitcoin::LegacySighash` from rust-bitcoin.
14+
//!
15+
216
extern crate secp256k1;
317

4-
use hashes::{sha256, Hash};
518
use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
619

720
fn verify<C: Verification>(
821
secp: &Secp256k1<C>,
9-
msg: &[u8],
22+
msg_digest: [u8; 32],
1023
sig: [u8; 64],
1124
pubkey: [u8; 33],
1225
) -> Result<bool, Error> {
13-
let msg = sha256::Hash::hash(msg);
14-
let msg = Message::from_digest(msg.to_byte_array());
26+
let msg = Message::from_digest(msg_digest);
1527
let sig = ecdsa::Signature::from_compact(&sig)?;
1628
let pubkey = PublicKey::from_slice(&pubkey)?;
1729

@@ -20,11 +32,10 @@ fn verify<C: Verification>(
2032

2133
fn sign<C: Signing>(
2234
secp: &Secp256k1<C>,
23-
msg: &[u8],
35+
msg_digest: [u8; 32],
2436
seckey: [u8; 32],
2537
) -> Result<ecdsa::Signature, Error> {
26-
let msg = sha256::Hash::hash(msg);
27-
let msg = Message::from_digest(msg.to_byte_array());
38+
let msg = Message::from_digest(msg_digest);
2839
let seckey = SecretKey::from_byte_array(seckey)?;
2940
Ok(secp.sign_ecdsa(msg, &seckey))
3041
}
@@ -40,11 +51,11 @@ fn main() {
4051
2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141,
4152
134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
4253
];
43-
let msg = b"This is some message";
54+
let msg_digest = *b"this must be secure hash output.";
4455

45-
let signature = sign(&secp, msg, seckey).unwrap();
56+
let signature = sign(&secp, msg_digest, seckey).unwrap();
4657

4758
let serialize_sig = signature.serialize_compact();
4859

49-
assert!(verify(&secp, msg, serialize_sig, pubkey).unwrap());
60+
assert!(verify(&secp, msg_digest, serialize_sig, pubkey).unwrap());
5061
}

examples/sign_verify_recovery.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
extern crate hashes;
21
extern crate secp256k1;
32

4-
use hashes::{sha256, Hash};
53
use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
64

75
fn recover<C: Verification>(
86
secp: &Secp256k1<C>,
9-
msg: &[u8],
7+
msg_digest: [u8; 32],
108
sig: [u8; 64],
119
recovery_id: u8,
1210
) -> Result<PublicKey, Error> {
13-
let msg = sha256::Hash::hash(msg);
14-
let msg = Message::from_digest(msg.to_byte_array());
11+
let msg = Message::from_digest(msg_digest);
1512
let id = ecdsa::RecoveryId::try_from(i32::from(recovery_id))?;
1613
let sig = ecdsa::RecoverableSignature::from_compact(&sig, id)?;
1714

@@ -20,11 +17,10 @@ fn recover<C: Verification>(
2017

2118
fn sign_recovery<C: Signing>(
2219
secp: &Secp256k1<C>,
23-
msg: &[u8],
20+
msg_digest: [u8; 32],
2421
seckey: [u8; 32],
2522
) -> Result<ecdsa::RecoverableSignature, Error> {
26-
let msg = sha256::Hash::hash(msg);
27-
let msg = Message::from_digest(msg.to_byte_array());
23+
let msg = Message::from_digest(msg_digest);
2824
let seckey = SecretKey::from_byte_array(seckey)?;
2925
Ok(secp.sign_ecdsa_recoverable(msg, &seckey))
3026
}
@@ -41,11 +37,11 @@ fn main() {
4137
134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
4238
])
4339
.unwrap();
44-
let msg = b"This is some message";
40+
let msg_digest = *b"this must be secure hash output.";
4541

46-
let signature = sign_recovery(&secp, msg, seckey).unwrap();
42+
let signature = sign_recovery(&secp, msg_digest, seckey).unwrap();
4743

4844
let (recovery_id, serialize_sig) = signature.serialize_compact();
4945

50-
assert_eq!(recover(&secp, msg, serialize_sig, recovery_id.to_u8()), Ok(pubkey));
46+
assert_eq!(recover(&secp, msg_digest, serialize_sig, recovery_id.to_u8()), Ok(pubkey));
5147
}

src/lib.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,23 @@
2828
//! trigger any assertion failures in the upstream library.
2929
//!
3030
//! ```rust
31-
//! # #[cfg(all(feature = "rand", feature = "hashes", feature = "std"))] {
31+
//! # #[cfg(all(feature = "rand", feature = "std"))] {
3232
//! use secp256k1::rand;
3333
//! use secp256k1::{Secp256k1, Message};
3434
//! use secp256k1::hashes::{sha256, Hash};
3535
//!
36+
//! // Our message to sign. We explicitly obtain a hash and convert it to a
37+
//! // `Message`. In a real application, we would produce a signature hash
38+
//! // type, e.g. `bitcoin::LegacySigHash`, which is convertible to `Message`
39+
//! // and can be passed directly to `sign_ecdsa`.
40+
//! const HELLO_WORLD_SHA2: [u8; 32] = [
41+
//! 0x31, 0x5f, 0x5b, 0xdb, 0x76, 0xd0, 0x78, 0xc4, 0x3b, 0x8a, 0xc0, 0x06, 0x4e, 0x4a, 0x01, 0x64,
42+
//! 0x61, 0x2b, 0x1f, 0xce, 0x77, 0xc8, 0x69, 0x34, 0x5b, 0xfc, 0x94, 0xc7, 0x58, 0x94, 0xed, 0xd3,
43+
//! ];
44+
//!
3645
//! let secp = Secp256k1::new();
3746
//! let (secret_key, public_key) = secp.generate_keypair(&mut rand::rng());
38-
//! let digest = sha256::Hash::hash("Hello World!".as_bytes());
39-
//! let message = Message::from_digest(digest.to_byte_array());
47+
//! let message = Message::from_digest(HELLO_WORLD_SHA2);
4048
//!
4149
//! let sig = secp.sign_ecdsa(message, &secret_key);
4250
//! assert!(secp.verify_ecdsa(&sig, message, &public_key).is_ok());
@@ -46,13 +54,19 @@
4654
//! If the "global-context" feature is enabled you have access to an alternate API.
4755
//!
4856
//! ```rust
49-
//! # #[cfg(all(feature = "global-context", feature = "hashes", feature = "rand", feature = "std"))] {
57+
//! # #[cfg(all(feature = "global-context", feature = "rand", feature = "std"))] {
5058
//! use secp256k1::{rand, generate_keypair, Message};
5159
//! use secp256k1::hashes::{sha256, Hash};
5260
//!
61+
//! // See previous example regarding this constant.
62+
//! const HELLO_WORLD_SHA2: [u8; 32] = [
63+
//! 0x31, 0x5f, 0x5b, 0xdb, 0x76, 0xd0, 0x78, 0xc4, 0x3b, 0x8a, 0xc0, 0x06, 0x4e, 0x4a, 0x01, 0x64,
64+
//! 0x61, 0x2b, 0x1f, 0xce, 0x77, 0xc8, 0x69, 0x34, 0x5b, 0xfc, 0x94, 0xc7, 0x58, 0x94, 0xed, 0xd3,
65+
//! ];
66+
//!
5367
//! let (secret_key, public_key) = generate_keypair(&mut rand::rng());
5468
//! let digest = sha256::Hash::hash("Hello World!".as_bytes());
55-
//! let message = Message::from_digest(digest.to_byte_array());
69+
//! let message = Message::from_digest(HELLO_WORLD_SHA2);
5670
//!
5771
//! let sig = secret_key.sign_ecdsa(message);
5872
//! assert!(sig.verify(message, &public_key).is_ok());

0 commit comments

Comments
 (0)