ethereum_private_key_to_address/
lib.rs1use anyhow::{Context, Result};
2use secp256k1::{PublicKey, Secp256k1, SecretKey};
3use sha3::{Digest, Keccak256};
4use std::str::FromStr;
5
6#[derive(Debug, PartialEq, Eq, Clone)]
21pub struct PrivateKey {
22 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 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 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 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 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 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 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 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}