1extern crate base58check;
2extern crate rand;
3extern crate ripemd;
4extern crate secp256k1;
5extern crate sha2;
6
7use base58check::ToBase58Check;
8use core::fmt::Display;
9use hex;
10use ripemd::Ripemd160;
11use secp256k1::{PublicKey, Secp256k1, SecretKey};
12use sha2::{Digest, Sha256};
13pub struct RunResult {
14 pub private_key: String,
15 pub public_key: String,
16 pub address: String,
17}
18
19pub enum RunError {
20 ParseError(String),
21}
22impl Display for RunError {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 RunError::ParseError(err) => write!(f, "Parse Error: {}", err),
26 }
27 }
28}
29
30pub struct Config {
31 pub private_key: Option<String>,
32 pub version: Option<u8>,
33}
34fn get_key_pair(config: &Config) -> Result<(SecretKey, PublicKey), String> {
35 let secp = Secp256k1::new();
36
37 if let Some(private_key) = &config.private_key {
38 let data =
39 hex::decode(&private_key).expect("Unable to decode secret key from the data given.");
40 let secret =
41 SecretKey::from_slice(&data).expect("Unable to create secret key from the data given.");
42 let public = PublicKey::from_secret_key(&secp, &secret);
43 return Ok((secret, public));
44 }
45
46 let mut rng = rand::thread_rng();
47 let (secret_key, public_key) = secp.generate_keypair(&mut rng);
48
49 Ok((secret_key, public_key))
50}
51
52pub fn run(config: Config) -> Result<RunResult, RunError> {
53 let key_pair = get_key_pair(&config);
55
56 match key_pair {
57 Ok((secret_key, public_key)) => {
58 let serialized_public_key = public_key.serialize_uncompressed();
60
61 let sha256_hash = Sha256::digest(&serialized_public_key[1..]);
63
64 let ripemd160_hash = Ripemd160::digest(&sha256_hash);
66
67 let version: u8 = config.version.unwrap_or(0x00);
69
70 let bitcoin_address = ripemd160_hash.to_base58check(version);
74
75 Ok(RunResult {
76 address: bitcoin_address,
77 private_key: secret_key.display_secret().to_string(),
78 public_key: hex::encode(public_key.serialize_uncompressed()),
79 })
80 }
81 Err(error) => Err(RunError::ParseError(error)),
82 }
83}