generate_bitcoin_paper_wallet/
private_key.rs1const 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#[derive(Debug, Clone)]
16pub struct PrivateKey(pub [u8; 32]);
17
18impl std::fmt::Display for PrivateKey {
19 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
21 write!(f, "{}", self.to_wif())
22 }
23}
24
25impl PrivateKey {
26 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 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}