Skip to main content

bitcoin_crypto_toolkit/
lib.rs

1use secp256k1::{Secp256k1, SecretKey, PublicKey};
2use sha2::{Sha256, Digest};
3use ripemd::Ripemd160;
4use base58::ToBase58;
5use hex;
6
7// Compute SHA256 hash of input data and return as hex string 
8pub fn sha256(data: &[u8]) -> String {
9    let mut hasher = Sha256::new();
10    hasher.update(data);
11    let result = hasher.finalize();
12    hex::encode(result)
13}
14
15// Compute RIPEMD160 hash of input data and return as hex string
16pub fn ripemd160(data: &[u8]) -> String {
17    let mut hasher = Ripemd160::new();
18    hasher.update(data);
19    let result = hasher.finalize();
20    hex::encode(result)
21}
22
23// Compute HASH160 (RIPEMD160 of SHA256) of input data and return as hex string
24pub fn hash160(data: &[u8]) -> String {
25    let sha = sha2::Sha256::digest(data);
26    let mut ripemd = Ripemd160::new();
27    ripemd.update(sha);
28    let result = ripemd.finalize();
29    hex::encode(result)
30}
31
32// Generate a new secp256k1 keypair
33pub fn generate_keypair() -> (SecretKey, PublicKey) {
34    let secp = Secp256k1::new();
35    let (secret_key, public_key) = secp.generate_keypair(&mut secp256k1::rand::thread_rng());
36    (secret_key, public_key)
37}
38
39// Derive Bitcoin P2PKH address from public key (compressed)
40pub fn derive_address(public_key: &PublicKey) -> String {
41    let compressed_pubkey = public_key.serialize();
42    let hash160 = hash160(&compressed_pubkey);
43    let hash160_bytes = hex::decode(&hash160).unwrap();
44
45    // Version byte for mainnet P2PKH
46    let mut address_bytes = vec![0x00];
47    address_bytes.extend(&hash160_bytes);
48
49    // Checksum: first 4 bytes of sha256(sha256(address_bytes))
50    let checksum = {
51        let mut hasher = Sha256::new();
52        hasher.update(&address_bytes);
53        let hash1 = hasher.finalize();
54        let mut hasher2 = Sha256::new();
55        hasher2.update(&hash1);
56        let hash2 = hasher2.finalize();
57        hash2[..4].to_vec()
58    };
59
60    address_bytes.extend(&checksum);
61    address_bytes.to_base58()
62}