generate_bitcoin_paper_wallet/
private_key.rs

1//! Bitcoin Private Keys
2
3const PRIVATE_KEY_LOWER_BOUND: [u8; 32] = {
4    let mut ret: [u8; 32] = [0x00; 32];
5    ret[31] = 0x01;
6    ret
7};
8
9const PRIVATE_KEY_UPPER_BOUND: [u8; 32] = [
10    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
11    0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40,
12];
13
14/// A bitcoin private key
15#[derive(Debug, Clone)]
16pub struct PrivateKey(pub [u8; 32]);
17
18impl std::fmt::Display for PrivateKey {
19    /// The private key is displayed in WIF format
20    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
21        write!(f, "{}", self.to_wif())
22    }
23}
24
25impl PrivateKey {
26    /// Converts the private to to Wallet Import Format
27    pub fn to_wif(&self) -> std::string::String {
28        let mut ret: [u8; 33] = [0; 33];
29        ret[0] = 0x80;
30        ret[1..33].copy_from_slice(&self.0[..]);
31
32        bitcoin::util::base58::check_encode_slice(&ret[..])
33    }
34
35    /// Generates a new random PrivateKey
36    ///
37    /// # Examples
38    ///
39    /// ```
40    /// use generate_bitcoin_paper_wallet::private_key::PrivateKey;
41    /// let private_key = PrivateKey::new();
42    /// ```
43    pub fn new() -> PrivateKey {
44        use rand::Rng;
45        let mut rng = rand::thread_rng();
46
47        let mut has_generated_key_within_bounds = false;
48        let mut key: [u8; 32] = [0; 32];
49        while !has_generated_key_within_bounds {
50            for i in 0..32 {
51                let index = 31 - i;
52                let candidate_value: u8 = rng.gen();
53                if !has_generated_key_within_bounds {
54                    if candidate_value > PRIVATE_KEY_UPPER_BOUND[index]
55                        && candidate_value < PRIVATE_KEY_LOWER_BOUND[index]
56                    {
57                        break;
58                    }
59                    key[index] = candidate_value;
60                    has_generated_key_within_bounds = true;
61                } else {
62                    key[index] = candidate_value;
63                }
64            }
65        }
66        PrivateKey(key)
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn displays_in_wif_format() {
76        let key = PrivateKey([
77            0x0C, 0x28, 0xFC, 0xA3, 0x86, 0xC7, 0xA2, 0x27, 0x60, 0x0B, 0x2F, 0xE5, 0x0B, 0x7C,
78            0xAE, 0x11, 0xEC, 0x86, 0xD3, 0xBF, 0x1F, 0xBE, 0x47, 0x1B, 0xE8, 0x98, 0x27, 0xE1,
79            0x9D, 0x72, 0xAA, 0x1D,
80        ]);
81
82        assert_eq!(
83            "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ",
84            format!("{}", key)
85        )
86    }
87}