1pub mod descriptor;
7pub mod helpers;
8pub mod lightning;
9pub mod message;
10pub mod miniscript;
11pub mod multisig;
12pub mod musig2_tx;
13pub mod ordinals;
14pub mod psbt;
15pub mod schnorr;
16pub mod scripts;
17pub mod sighash;
18pub mod silent_payments;
19pub mod taproot;
20pub mod tapscript;
21pub mod transaction;
22
23use crate::crypto;
24use crate::encoding;
25use crate::error::SignerError;
26use crate::traits;
27use k256::ecdsa::signature::hazmat::PrehashSigner;
28use k256::ecdsa::signature::hazmat::PrehashVerifier;
29use k256::ecdsa::{Signature as K256Signature, SigningKey, VerifyingKey};
30use zeroize::Zeroizing;
31
32#[derive(Debug, Clone, PartialEq, Eq)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35#[must_use]
36pub struct BitcoinSignature {
37 der_bytes: Vec<u8>,
39}
40
41impl BitcoinSignature {
42 #[must_use]
44 pub fn to_bytes(&self) -> Vec<u8> {
45 self.der_bytes.clone()
46 }
47
48 #[must_use]
50 pub fn der_bytes(&self) -> &[u8] {
51 &self.der_bytes
52 }
53
54 pub fn from_bytes(der: &[u8]) -> Result<Self, SignerError> {
56 K256Signature::from_der(der).map_err(|e| SignerError::InvalidSignature(e.to_string()))?;
58 Ok(Self {
59 der_bytes: der.to_vec(),
60 })
61 }
62}
63
64impl core::fmt::Display for BitcoinSignature {
65 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66 for byte in &self.der_bytes {
67 write!(f, "{byte:02x}")?;
68 }
69 Ok(())
70 }
71}
72
73pub fn double_sha256(data: &[u8]) -> [u8; 32] {
75 crypto::double_sha256(data)
76}
77
78pub struct BitcoinSigner {
83 signing_key: SigningKey,
84}
85
86impl BitcoinSigner {
89 fn sign_digest(&self, digest: &[u8; 32]) -> Result<BitcoinSignature, SignerError> {
91 let sig: K256Signature = self
92 .signing_key
93 .sign_prehash(digest)
94 .map_err(|e| SignerError::SigningFailed(e.to_string()))?;
95
96 let der = sig.to_der();
98 Ok(BitcoinSignature {
99 der_bytes: der.as_bytes().to_vec(),
100 })
101 }
102
103 #[must_use]
111 pub fn to_wif(&self) -> Zeroizing<String> {
112 let mut payload = Zeroizing::new(Vec::with_capacity(38));
113 payload.push(0x80); payload.extend_from_slice(&self.signing_key.to_bytes());
115 payload.push(0x01); let checksum = double_sha256(&payload);
117 payload.extend_from_slice(&checksum[..4]);
118 Zeroizing::new(bs58::encode(&*payload).into_string())
119 }
120
121 #[must_use]
128 pub fn to_wif_testnet(&self) -> Zeroizing<String> {
129 let mut payload = Zeroizing::new(Vec::with_capacity(38));
130 payload.push(0xEF); payload.extend_from_slice(&self.signing_key.to_bytes());
132 payload.push(0x01); let checksum = double_sha256(&payload);
134 payload.extend_from_slice(&checksum[..4]);
135 Zeroizing::new(bs58::encode(&*payload).into_string())
136 }
137
138 pub fn from_wif(wif: &str) -> Result<Self, SignerError> {
142 use crate::traits::KeyPair;
143 let decoded = Zeroizing::new(
144 bs58::decode(wif)
145 .into_vec()
146 .map_err(|e| SignerError::InvalidPrivateKey(format!("invalid WIF base58: {e}")))?,
147 );
148
149 if decoded.len() != 37 && decoded.len() != 38 {
151 return Err(SignerError::InvalidPrivateKey(format!(
152 "WIF must be 37 or 38 bytes, got {}",
153 decoded.len()
154 )));
155 }
156
157 let version = decoded[0];
159 if version != 0x80 && version != 0xEF {
160 return Err(SignerError::InvalidPrivateKey(format!(
161 "invalid WIF version: 0x{version:02x}"
162 )));
163 }
164
165 let payload_len = decoded.len() - 4;
167 let checksum = double_sha256(&decoded[..payload_len]);
168 use subtle::ConstantTimeEq;
169 if decoded[payload_len..].ct_eq(&checksum[..4]).unwrap_u8() != 1 {
170 return Err(SignerError::InvalidPrivateKey(
171 "invalid WIF checksum".into(),
172 ));
173 }
174
175 let key_bytes = &decoded[1..33];
177
178 Self::from_bytes(key_bytes)
179 }
180
181 #[must_use]
185 pub fn p2pkh_address(&self) -> String {
186 let pubkey = self.signing_key.verifying_key().to_sec1_bytes();
187 let h160 = hash160(&pubkey);
188 base58check_encode(0x00, &h160)
189 }
190
191 pub fn p2wpkh_address(&self) -> Result<String, SignerError> {
195 let pubkey = self.signing_key.verifying_key().to_sec1_bytes();
196 let h160 = hash160(&pubkey);
197 bech32_encode("bc", 0, &h160)
198 }
199
200 pub fn p2pkh_testnet_address(&self) -> String {
202 let pubkey = self.signing_key.verifying_key().to_sec1_bytes();
203 let h160 = hash160(&pubkey);
204 base58check_encode(0x6F, &h160) }
206
207 pub fn p2wpkh_testnet_address(&self) -> Result<String, SignerError> {
209 let pubkey = self.signing_key.verifying_key().to_sec1_bytes();
210 let h160 = hash160(&pubkey);
211 bech32_encode("tb", 0, &h160)
212 }
213
214 pub fn sign_message(&self, message: &[u8]) -> Result<BitcoinSignature, SignerError> {
219 let digest = bitcoin_message_hash(message);
220 self.sign_digest(&digest)
221 }
222}
223
224pub fn hash160(data: &[u8]) -> [u8; 20] {
226 crypto::hash160(data)
227}
228
229fn base58check_encode(version: u8, payload: &[u8]) -> String {
231 encoding::base58check_encode(version, payload)
232}
233
234pub(crate) fn bech32_encode(
236 hrp: &str,
237 witness_version: u8,
238 program: &[u8],
239) -> Result<String, SignerError> {
240 encoding::bech32_encode(hrp, witness_version, program)
241}
242
243pub fn bitcoin_message_hash(message: &[u8]) -> [u8; 32] {
247 let mut data = Vec::new();
248 data.extend_from_slice(b"\x18Bitcoin Signed Message:\n");
250 data.extend_from_slice(&varint_encode(message.len()));
252 data.extend_from_slice(message);
253 double_sha256(&data)
254}
255
256fn varint_encode(n: usize) -> Vec<u8> {
258 let mut buf = Vec::new();
259 encoding::encode_compact_size(&mut buf, n as u64);
260 buf
261}
262
263pub fn validate_address(address: &str) -> bool {
268 validate_mainnet_address(address) || validate_testnet_address(address)
269}
270
271pub fn validate_mainnet_address(address: &str) -> bool {
273 if address.starts_with("bc1") {
274 bech32::segwit::decode(address).is_ok()
276 } else if address.starts_with('1') || address.starts_with('3') {
277 validate_base58check(address, &[0x00, 0x05])
279 } else {
280 false
281 }
282}
283
284pub fn validate_testnet_address(address: &str) -> bool {
286 if address.starts_with("tb1") {
287 bech32::segwit::decode(address).is_ok()
288 } else if address.starts_with('m') || address.starts_with('n') || address.starts_with('2') {
289 validate_base58check(address, &[0x6F, 0xC4])
290 } else {
291 false
292 }
293}
294
295fn validate_base58check(address: &str, valid_versions: &[u8]) -> bool {
297 let decoded = match bs58::decode(address).into_vec() {
298 Ok(d) => d,
299 Err(_) => return false,
300 };
301 if decoded.len() != 25 {
302 return false;
303 }
304 if !valid_versions.contains(&decoded[0]) {
306 return false;
307 }
308 let checksum = double_sha256(&decoded[..21]);
310 use subtle::ConstantTimeEq;
311 decoded[21..25].ct_eq(&checksum[..4]).unwrap_u8() == 1
312}
313
314impl traits::Signer for BitcoinSigner {
315 type Signature = BitcoinSignature;
316 type Error = SignerError;
317
318 fn sign(&self, message: &[u8]) -> Result<BitcoinSignature, SignerError> {
319 let digest = double_sha256(message);
320 self.sign_digest(&digest)
321 }
322
323 fn sign_prehashed(&self, digest: &[u8]) -> Result<BitcoinSignature, SignerError> {
324 if digest.len() != 32 {
325 return Err(SignerError::InvalidHashLength {
326 expected: 32,
327 got: digest.len(),
328 });
329 }
330 let mut hash = [0u8; 32];
331 hash.copy_from_slice(digest);
332 self.sign_digest(&hash)
333 }
334
335 fn public_key_bytes(&self) -> Vec<u8> {
336 self.signing_key.verifying_key().to_sec1_bytes().to_vec()
337 }
338
339 fn public_key_bytes_uncompressed(&self) -> Vec<u8> {
340 self.signing_key
341 .verifying_key()
342 .to_encoded_point(false)
343 .as_bytes()
344 .to_vec()
345 }
346}
347
348impl traits::KeyPair for BitcoinSigner {
349 fn generate() -> Result<Self, SignerError> {
350 let mut key_bytes = zeroize::Zeroizing::new([0u8; 32]);
351 crate::security::secure_random(&mut *key_bytes)?;
352 let signing_key = SigningKey::from_bytes((&*key_bytes).into())
353 .map_err(|e| SignerError::InvalidPrivateKey(e.to_string()))?;
354 Ok(Self { signing_key })
355 }
356
357 fn from_bytes(private_key: &[u8]) -> Result<Self, SignerError> {
358 if private_key.len() != 32 {
359 return Err(SignerError::InvalidPrivateKey(format!(
360 "expected 32 bytes, got {}",
361 private_key.len()
362 )));
363 }
364 let signing_key = SigningKey::from_bytes(private_key.into())
365 .map_err(|e| SignerError::InvalidPrivateKey(e.to_string()))?;
366 Ok(Self { signing_key })
367 }
368
369 fn private_key_bytes(&self) -> Zeroizing<Vec<u8>> {
370 Zeroizing::new(self.signing_key.to_bytes().to_vec())
371 }
372}
373
374pub struct BitcoinVerifier {
381 verifying_key: VerifyingKey,
382}
383
384impl BitcoinVerifier {
385 pub fn from_public_key_bytes(bytes: &[u8]) -> Result<Self, SignerError> {
387 let verifying_key = VerifyingKey::from_sec1_bytes(bytes)
388 .map_err(|e| SignerError::InvalidPublicKey(e.to_string()))?;
389 Ok(Self { verifying_key })
390 }
391
392 fn verify_digest(
393 &self,
394 digest: &[u8; 32],
395 signature: &BitcoinSignature,
396 ) -> Result<bool, SignerError> {
397 let sig = K256Signature::from_der(&signature.der_bytes)
398 .map_err(|e| SignerError::InvalidSignature(e.to_string()))?;
399 match self.verifying_key.verify_prehash(digest, &sig) {
400 Ok(()) => Ok(true),
401 Err(_) => Ok(false),
402 }
403 }
404}
405
406impl traits::Verifier for BitcoinVerifier {
407 type Signature = BitcoinSignature;
408 type Error = SignerError;
409
410 fn verify(&self, message: &[u8], signature: &BitcoinSignature) -> Result<bool, SignerError> {
411 let digest = double_sha256(message);
412 self.verify_digest(&digest, signature)
413 }
414
415 fn verify_prehashed(
416 &self,
417 digest: &[u8],
418 signature: &BitcoinSignature,
419 ) -> Result<bool, SignerError> {
420 if digest.len() != 32 {
421 return Err(SignerError::InvalidHashLength {
422 expected: 32,
423 got: digest.len(),
424 });
425 }
426 let mut hash = [0u8; 32];
427 hash.copy_from_slice(digest);
428 self.verify_digest(&hash, signature)
429 }
430}
431
432#[cfg(test)]
433#[allow(clippy::unwrap_used, clippy::expect_used)]
434mod tests {
435 use super::*;
436 use crate::traits::{KeyPair, Signer, Verifier};
437
438 #[test]
439 fn test_generate_keypair() {
440 let signer = BitcoinSigner::generate().unwrap();
441 let pubkey = signer.public_key_bytes();
442 assert_eq!(pubkey.len(), 33); }
444
445 #[test]
446 fn test_from_bytes_roundtrip() {
447 let signer = BitcoinSigner::generate().unwrap();
448 let key_bytes = signer.private_key_bytes();
449 let restored = BitcoinSigner::from_bytes(&key_bytes).unwrap();
450 assert_eq!(signer.public_key_bytes(), restored.public_key_bytes());
451 }
452
453 #[test]
454 fn test_sign_verify_roundtrip() {
455 let signer = BitcoinSigner::generate().unwrap();
456 let msg = b"hello bitcoin";
457 let sig = signer.sign(msg).unwrap();
458 let verifier = BitcoinVerifier::from_public_key_bytes(&signer.public_key_bytes()).unwrap();
459 assert!(verifier.verify(msg, &sig).unwrap());
460 }
461
462 #[test]
463 fn test_double_sha256() {
464 let result = double_sha256(b"hello");
467 assert_eq!(
468 hex::encode(result),
469 "9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50"
470 );
471 }
472
473 #[test]
474 fn test_rfc6979_deterministic() {
475 let privkey =
477 hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
478 .unwrap();
479 let signer = BitcoinSigner::from_bytes(&privkey).unwrap();
480 let sig1 = signer.sign(b"Satoshi Nakamoto").unwrap();
481 let sig2 = signer.sign(b"Satoshi Nakamoto").unwrap();
482 assert_eq!(sig1.der_bytes(), sig2.der_bytes());
483 }
484
485 #[test]
486 fn test_rfc6979_known_vector_privkey_1() {
487 let privkey =
490 hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
491 .unwrap();
492 let signer = BitcoinSigner::from_bytes(&privkey).unwrap();
493
494 let pubkey = signer.public_key_bytes();
496 assert_eq!(
497 hex::encode(&pubkey).to_uppercase(),
498 "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
499 );
500
501 let sig = signer.sign(b"Satoshi Nakamoto").unwrap();
503 assert!(!sig.der_bytes().is_empty());
505 let verifier = BitcoinVerifier::from_public_key_bytes(&pubkey).unwrap();
507 assert!(verifier.verify(b"Satoshi Nakamoto", &sig).unwrap());
508 }
509
510 #[test]
511 fn test_rfc6979_known_vector_privkey_2() {
512 let privkey =
514 hex::decode("0000000000000000000000000000000000000000000000000000000000000002")
515 .unwrap();
516 let signer = BitcoinSigner::from_bytes(&privkey).unwrap();
517 let sig = signer.sign(b"Satoshi Nakamoto").unwrap();
518 let verifier = BitcoinVerifier::from_public_key_bytes(&signer.public_key_bytes()).unwrap();
519 assert!(verifier.verify(b"Satoshi Nakamoto", &sig).unwrap());
520 let sig2 = signer.sign(b"Satoshi Nakamoto").unwrap();
522 assert_eq!(sig.der_bytes(), sig2.der_bytes());
523 }
524
525 #[test]
526 fn test_der_encoding() {
527 let signer = BitcoinSigner::generate().unwrap();
528 let sig = signer.sign(b"DER test").unwrap();
529 assert_eq!(sig.der_bytes()[0], 0x30);
531 assert!(sig.der_bytes().len() >= 68 && sig.der_bytes().len() <= 72);
533 }
534
535 #[test]
536 fn test_invalid_privkey_rejected() {
537 assert!(BitcoinSigner::from_bytes(&[0u8; 32]).is_err());
538 assert!(BitcoinSigner::from_bytes(&[1u8; 31]).is_err());
539 assert!(BitcoinSigner::from_bytes(&[1u8; 33]).is_err());
540 }
541
542 #[test]
543 fn test_tampered_sig_fails() {
544 let signer = BitcoinSigner::generate().unwrap();
545 let sig = signer.sign(b"tamper test").unwrap();
546 let verifier = BitcoinVerifier::from_public_key_bytes(&signer.public_key_bytes()).unwrap();
547
548 let tampered_bytes: Vec<u8> = {
549 let mut b = sig.to_bytes();
550 if let Some(byte) = b.last_mut() {
551 *byte ^= 0xff;
552 }
553 b
554 };
555 let tampered = BitcoinSignature::from_bytes(&tampered_bytes);
556 if let Ok(t) = tampered {
558 let result = verifier.verify(b"tamper test", &t);
559 assert!(result.is_err() || !result.unwrap());
560 }
561 }
562
563 #[test]
564 fn test_wrong_pubkey_fails() {
565 let signer1 = BitcoinSigner::generate().unwrap();
566 let signer2 = BitcoinSigner::generate().unwrap();
567 let sig = signer1.sign(b"wrong key test").unwrap();
568 let verifier = BitcoinVerifier::from_public_key_bytes(&signer2.public_key_bytes()).unwrap();
569 assert!(!verifier.verify(b"wrong key test", &sig).unwrap());
570 }
571
572 #[test]
573 fn test_empty_message() {
574 let signer = BitcoinSigner::generate().unwrap();
575 let sig = signer.sign(b"").unwrap();
576 let verifier = BitcoinVerifier::from_public_key_bytes(&signer.public_key_bytes()).unwrap();
577 assert!(verifier.verify(b"", &sig).unwrap());
578 }
579
580 #[test]
581 fn test_sign_prehashed_roundtrip() {
582 let signer = BitcoinSigner::generate().unwrap();
583 let msg = b"prehash btc";
584 let digest = double_sha256(msg);
585 let sig = signer.sign_prehashed(&digest).unwrap();
586 let verifier = BitcoinVerifier::from_public_key_bytes(&signer.public_key_bytes()).unwrap();
587 assert!(verifier.verify_prehashed(&digest, &sig).unwrap());
588 }
589
590 #[test]
591 fn test_zeroize_on_drop() {
592 let signer = BitcoinSigner::generate().unwrap();
593 let key_bytes = signer.private_key_bytes();
594 let _: Zeroizing<Vec<u8>> = key_bytes;
595 drop(signer);
596 }
597
598 #[test]
601 fn test_p2pkh_known_address_privkey_1() {
602 let sk = hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
605 .unwrap();
606 let signer = BitcoinSigner::from_bytes(&sk).unwrap();
607 assert_eq!(signer.p2pkh_address(), "1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH");
608 }
609
610 #[test]
611 fn test_p2wpkh_known_address_privkey_1() {
612 let sk = hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
614 .unwrap();
615 let signer = BitcoinSigner::from_bytes(&sk).unwrap();
616 assert_eq!(
617 signer.p2wpkh_address().unwrap(),
618 "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"
619 );
620 }
621
622 #[test]
625 fn test_wif_encode_known() {
626 let sk = hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
628 .unwrap();
629 let signer = BitcoinSigner::from_bytes(&sk).unwrap();
630 let wif = signer.to_wif();
631 assert!(wif.starts_with('K') || wif.starts_with('L'));
632 assert_eq!(wif.len(), 52); }
634
635 #[test]
636 fn test_wif_roundtrip() {
637 let signer = BitcoinSigner::generate().unwrap();
638 let wif = signer.to_wif();
639 let restored = BitcoinSigner::from_wif(&wif).unwrap();
640 assert_eq!(&*signer.private_key_bytes(), &*restored.private_key_bytes());
641 assert_eq!(signer.p2pkh_address(), restored.p2pkh_address());
642 }
643
644 #[test]
647 fn test_validate_known_addresses() {
648 assert!(validate_address("1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH")); assert!(validate_address(
650 "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"
651 )); assert!(!validate_address(""));
653 assert!(!validate_address("1invalid"));
654 assert!(!validate_address("bc1qinvalid"));
655 }
656
657 #[test]
660 fn test_bip137_sign_verify_roundtrip() {
661 let signer = BitcoinSigner::generate().unwrap();
662 let sig = signer.sign_message(b"Hello Bitcoin").unwrap();
663 assert_eq!(sig.der_bytes()[0], 0x30); let verifier = BitcoinVerifier::from_public_key_bytes(&signer.public_key_bytes()).unwrap();
667 let digest = bitcoin_message_hash(b"Hello Bitcoin");
668 assert!(verifier.verify_prehashed(&digest, &sig).unwrap());
669 }
670}