ethereum_private_key_to_address/
lib.rs

1use anyhow::{Context, Result};
2use secp256k1::{PublicKey, Secp256k1, SecretKey};
3use sha3::{Digest, Keccak256};
4use std::str::FromStr;
5
6/// PrivateKey struct that contains method that will convert your private key to an ethereum
7/// address
8///
9/// To calculate Ethereum address from your private key follow these steps:
10/// ```
11/// use std::str::FromStr;
12/// use ethereum_private_key_to_address::PrivateKey;
13///
14/// // 1.) Create PrivateKey struct from str.
15/// let private_key = PrivateKey::from_str("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80").unwrap();
16///
17/// // 2.) Call the `address()` method on  your private key
18/// let address = private_key.address();
19/// ```
20#[derive(Debug, PartialEq, Eq, Clone)]
21pub struct PrivateKey {
22    /// Private Key
23    private_key: SecretKey,
24}
25
26impl FromStr for PrivateKey {
27    type Err = anyhow::Error;
28
29    fn from_str(s: &str) -> Result<Self, Self::Err> {
30        let private_key = s.replace("0x", "");
31        let private_key = SecretKey::from_str(&private_key)
32            .context("Problem parsing private key, check if your private key is correct")?;
33
34        Ok(Self { private_key })
35    }
36}
37
38impl From<secp256k1::SecretKey> for PrivateKey {
39    fn from(value: secp256k1::SecretKey) -> Self {
40        Self { private_key: value }
41    }
42}
43
44impl From<&[u8]> for PrivateKey {
45    fn from(value: &[u8]) -> Self {
46        let private_key = SecretKey::from_slice(value).expect("Failed to parse the private key. Check if your encoding to &[u8] is correct and try again. Or you can try the from_str() method");
47        Self { private_key }
48    }
49}
50
51impl From<&[u8; 32]> for PrivateKey {
52    fn from(value: &[u8; 32]) -> Self {
53        let private_key = SecretKey::from_slice(value).expect("Failed to parse the private key. Check if your encoding to &[u8] is correct and try again. Or you can try the from_str() method");
54        Self { private_key }
55    }
56}
57
58impl From<[u8; 32]> for PrivateKey {
59    fn from(value: [u8; 32]) -> Self {
60        let private_key = SecretKey::from_slice(&value).expect("Failed to parse the private key. Check if your encoding to &[u8] is correct and try again. Or you can try the from_str() method");
61        Self { private_key }
62    }
63}
64
65impl From<Vec<u8>> for PrivateKey {
66    fn from(value: Vec<u8>) -> Self {
67        let private_key = SecretKey::from_slice(&value.to_vec()).expect("Failed to parse the private key. Check if your encoding to &[u8] is correct and try again. Or you can try the from_str() method");
68        Self { private_key }
69    }
70}
71
72impl PrivateKey {
73    /// Calculates the address from the private key
74    /// ```
75    /// use ethereum_private_key_to_address::PrivateKey;
76    /// use std::str::FromStr;
77    ///
78    /// let pk = PrivateKey::from_str("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80").unwrap();
79    ///
80    /// println!("{}", pk.address());
81    /// ```
82    pub fn address(&self) -> String {
83        let secp = Secp256k1::new();
84        let public_key = self.private_key.public_key(&secp);
85        let public_key = public_key.serialize_uncompressed()[1..].to_vec();
86        let mut hasher = Keccak256::new();
87        hasher.update(public_key);
88        let address = hasher.finalize();
89        let mut addr = hex::encode(&address[12..32]);
90        addr.insert_str(0, "0x");
91        addr
92    }
93
94    /// Converts your private key in the &[u8] format to PrivateKey struct
95    pub fn from_slice(slice: &[u8]) -> Result<Self> {
96        let private_key = SecretKey::from_slice(slice).context("Failed to parse given private key. Make sure your encoding is correct or try the from_str() method")?;
97
98        Ok(Self { private_key })
99    }
100
101    /// Returns Full 64 byte Public Key from Private Key without 0x04 in the front as a String. 0x04 is used to
102    /// specify the type of the public key. 0x04 in front means the public key is uncompressed
103    pub fn public_key(&self) -> String {
104        let secp = Secp256k1::new();
105        let public_key = PublicKey::from_secret_key(&secp, &self.private_key);
106        hex::encode(&public_key.serialize_uncompressed()[1..])
107    }
108
109    /// Returns Full 65 byte Public Key including the prefix as a String. In this case prefix is 0x04. 0x04 is used
110    /// to specify the type of the public key. If you want to get public key without the prefix
111    /// call the `public_key()` method.
112    pub fn public_key_full(&self) -> String {
113        let secp = Secp256k1::new();
114        let public_key = PublicKey::from_secret_key(&secp, &self.private_key);
115        hex::encode(public_key.serialize_uncompressed())
116    }
117
118    /// Returns the x-coordiante of the public key as a string.
119    pub fn public_key_x(&self) -> String {
120        let secp = Secp256k1::new();
121        let public_key = PublicKey::from_secret_key(&secp, &self.private_key);
122        hex::encode(&public_key.serialize_uncompressed()[1..33])
123    }
124
125    /// Returns the y-coordinate of the public key
126    pub fn public_key_y(&self) -> String {
127        let secp = Secp256k1::new();
128        let public_key = PublicKey::from_secret_key(&secp, &self.private_key);
129        hex::encode(&public_key.serialize_uncompressed()[33..])
130    }
131
132    /// Returns the entire public key in [u8; 65] format
133    pub fn public_key_slice(&self) -> [u8; 65] {
134        let secp = Secp256k1::new();
135        let public_key = PublicKey::from_secret_key(&secp, &self.private_key);
136        public_key.serialize_uncompressed()
137    }
138}
139
140#[cfg(test)]
141pub mod test {
142    use crate::PrivateKey;
143    use hex::FromHex;
144    use std::str::FromStr;
145
146    fn test_account(priv_key: &str, addr: &str) {
147        let private_key = PrivateKey::from_str(priv_key).unwrap();
148        assert_eq!(addr, private_key.address());
149    }
150
151    #[test]
152    fn test_account_one() {
153        test_account(
154            "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
155            "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
156        );
157    }
158
159    #[test]
160    fn test_account_two() {
161        test_account(
162            "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d",
163            "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
164        )
165    }
166    #[test]
167    fn test_account_three() {
168        test_account(
169            "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a",
170            "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc",
171        )
172    }
173
174    #[test]
175    fn test_account_four() {
176        let private_key =
177            Vec::from_hex("8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba")
178                .unwrap();
179        let private_key = PrivateKey::from(private_key);
180        assert_eq!(
181            "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc",
182            private_key.address()
183        );
184    }
185
186    #[test]
187    fn test_account_from_slice() {
188        let private_key =
189            hex::decode("7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6")
190                .unwrap();
191        let private_key = PrivateKey::from(&private_key[..]);
192        assert_eq!(
193            "0x90f79bf6eb2c4f870365e785982e1f101e93b906",
194            private_key.address()
195        );
196    }
197
198    #[test]
199    fn test_account_from_vec() {
200        let private_key = PrivateKey::from(
201            hex::decode("47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a")
202                .unwrap(),
203        );
204        assert_eq!(
205            "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65",
206            private_key.address()
207        );
208    }
209
210    #[test]
211    fn test_account_from_fixed_bytes() {
212        let private_key =
213            hex::decode("47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a")
214                .unwrap();
215        let private_key = PrivateKey::from(TryInto::<[u8; 32]>::try_into(private_key).unwrap());
216        assert_eq!(
217            "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65",
218            private_key.address()
219        );
220    }
221
222    #[test]
223    fn test_account_from_slice_custom() {
224        let private_key =
225            hex::decode("92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e")
226                .unwrap();
227        let private_key = PrivateKey::from_slice(&private_key);
228        assert_eq!(
229            "0x976ea74026e726554db657fa54763abd0c3a0aa9",
230            private_key.unwrap().address()
231        );
232    }
233}