1use std::convert::TryInto;
7
8use ring::hmac::{sign as hmac, Key as HmacKey, HMAC_SHA512};
9pub use secp256k1::{Error as SecpError, PublicKey, Secp256k1, SecretKey as PrivateKey};
10use thiserror::Error;
11
12#[derive(Debug, Error)]
14#[error("index error: {0}")]
15pub struct IndexError(u32);
16
17#[derive(Debug, Error)]
19#[error("hardened derivation error")]
20pub struct HardenedDeriveError;
21
22#[derive(Clone, Copy, Debug)]
24pub enum ChildNumber {
25 Normal(u32),
27 Hardened(u32),
29}
30
31#[derive(Debug, Error)]
33pub enum DeriveError {
34 #[error("hardened derivation error")]
36 HardenedDeriveError,
37 #[error(transparent)]
39 InvalidTweak(SecpError),
40}
41
42impl ChildNumber {
43 pub fn from_normal_index(index: u32) -> Result<Self, IndexError> {
46 if index & (1 << 31) == 0 {
47 Ok(ChildNumber::Normal(index))
48 } else {
49 Err(IndexError(index))
50 }
51 }
52
53 pub fn from_hardened_index(index: u32) -> Result<Self, IndexError> {
56 if index & (1 << 31) == 0 {
57 Ok(ChildNumber::Hardened(index))
58 } else {
59 Err(IndexError(index))
60 }
61 }
62}
63
64impl From<u32> for ChildNumber {
65 fn from(number: u32) -> Self {
66 if number & (1 << 31) != 0 {
67 ChildNumber::Hardened(number ^ (1 << 31))
68 } else {
69 ChildNumber::Normal(number)
70 }
71 }
72}
73
74#[derive(Debug, Copy, Clone, PartialEq, Eq)]
78pub struct ExtendedPublicKey {
79 public_key: PublicKey,
80 chain_code: [u8; 32],
81}
82
83impl ExtendedPublicKey {
84 pub fn new_master(public_key: PublicKey, chain_code: [u8; 32]) -> Self {
86 Self {
87 public_key,
88 chain_code,
89 }
90 }
91
92 pub fn get_public_key(&self) -> &PublicKey {
94 &self.public_key
95 }
96
97 pub fn into_public_key(self) -> PublicKey {
99 self.public_key
100 }
101
102 pub fn as_parts(&self) -> (PublicKey, [u8; 32]) {
104 (self.public_key, self.chain_code)
105 }
106
107 pub fn into_parts(self) -> (PublicKey, [u8; 32]) {
109 (self.public_key, self.chain_code)
110 }
111
112 pub fn derive_public_path<C: secp256k1::Verification, P>(
116 &self,
117 secp: &Secp256k1<C>,
118 path: &P,
119 ) -> Result<ExtendedPublicKey, DeriveError>
120 where
121 for<'a> &'a P: IntoIterator<Item = &'a ChildNumber>,
122 {
123 let mut path_iter = path.into_iter();
124 let mut public_key = if let Some(num) = path_iter.next() {
125 self.derive_public_child(secp, *num)?
126 } else {
127 return Ok(*self);
128 };
129 for num in path_iter {
130 public_key = public_key.derive_public_child(secp, *num)?
131 }
132 Ok(public_key)
133 }
134
135 pub fn derive_public_child<C: secp256k1::Verification>(
137 &self,
138 secp: &Secp256k1<C>,
139 child_number: ChildNumber,
140 ) -> Result<ExtendedPublicKey, DeriveError> {
141 let index = match child_number {
142 ChildNumber::Hardened(_) => return Err(DeriveError::HardenedDeriveError),
143 ChildNumber::Normal(index) => index,
144 };
145 let key = HmacKey::new(HMAC_SHA512, &self.chain_code);
146 let data = [&self.public_key.serialize()[..], &index.to_be_bytes()[..]].concat();
147 let hmac_result = hmac(&key, &data);
148
149 let private_key = PrivateKey::from_slice(&hmac_result.as_ref()[..32]).unwrap(); let chain_code: [u8; 32] = hmac_result.as_ref()[32..].try_into().unwrap(); let mut public_key = self.public_key;
152 public_key
153 .add_exp_assign(secp, &private_key[..])
154 .map_err(DeriveError::InvalidTweak)?;
155
156 Ok(ExtendedPublicKey {
157 public_key,
158 chain_code,
159 })
160 }
161}
162
163#[derive(Debug, Copy, Clone, PartialEq, Eq)]
167pub struct ExtendedPrivateKey {
168 private_key: PrivateKey,
169 chain_code: [u8; 32],
170}
171
172impl ExtendedPrivateKey {
173 pub fn new_master(private_key: PrivateKey, chain_code: [u8; 32]) -> Self {
175 ExtendedPrivateKey {
176 private_key,
177 chain_code,
178 }
179 }
180
181 pub fn get_private_key(&self) -> &PrivateKey {
183 &self.private_key
184 }
185
186 pub fn into_private_key(self) -> PrivateKey {
188 self.private_key
189 }
190
191 pub fn into_parts(self) -> (PrivateKey, [u8; 32]) {
193 (self.private_key, self.chain_code)
194 }
195
196 pub fn derive_private_path<C: secp256k1::Signing, P>(
200 &self,
201 secp: &Secp256k1<C>,
202 path: &P,
203 ) -> ExtendedPrivateKey
204 where
205 for<'a> &'a P: IntoIterator<Item = &'a ChildNumber>,
206 {
207 let mut path_iter = path.into_iter();
208 let mut private_key = if let Some(num) = path_iter.next() {
209 self.derive_private_child(secp, *num)
210 } else {
211 return *self;
212 };
213 for num in path_iter {
214 private_key = private_key.derive_private_child(secp, *num);
215 }
216 private_key
217 }
218
219 pub fn derive_private_child<C: secp256k1::Signing>(
221 &self,
222 secp: &Secp256k1<C>,
223 child_number: ChildNumber,
224 ) -> ExtendedPrivateKey {
225 let key = HmacKey::new(HMAC_SHA512, &self.chain_code);
227 let hmac_result = match child_number {
228 ChildNumber::Normal(index) => {
229 let raw_public_key =
231 PublicKey::from_secret_key(secp, &self.private_key).serialize();
232 let data = [&raw_public_key[..], &index.to_be_bytes()].concat();
233 hmac(&key, &data)
234 }
235 ChildNumber::Hardened(index) => {
236 let data = [&[0], &self.private_key[..], &index.to_be_bytes()].concat();
238 hmac(&key, &data)
239 }
240 };
241
242 let mut private_key = PrivateKey::from_slice(&hmac_result.as_ref()[..32]).unwrap(); private_key.add_assign(&self.private_key[..]).unwrap(); let chain_code = hmac_result.as_ref()[32..].try_into().unwrap(); ExtendedPrivateKey {
249 private_key,
250 chain_code,
251 }
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258 use rand::thread_rng;
259 use secp256k1::Secp256k1;
260
261 #[test]
262 fn child_derivation() {
263 let secp = Secp256k1::new();
264 let mut rng = thread_rng();
265 let private_key = PrivateKey::new(&mut rng);
266 let public_key = PublicKey::from_secret_key(&secp, &private_key);
267 let hd_private_key = ExtendedPrivateKey::new_master(private_key, [0; 32]);
268 let hd_public_key = ExtendedPublicKey::new_master(public_key, [0; 32]);
269
270 let new_hd_private_key =
271 hd_private_key.derive_private_child(&secp, ChildNumber::Normal(32));
272 let new_hd_public_key = hd_public_key
273 .derive_public_child(&secp, ChildNumber::Normal(32))
274 .unwrap();
275
276 assert_eq!(
277 PublicKey::from_secret_key(&secp, &new_hd_private_key.into_private_key()),
278 new_hd_public_key.into_public_key()
279 );
280 }
281
282 #[test]
283 fn child_derivation_normal_path_a() {
284 let secp = Secp256k1::new();
285 let mut rng = thread_rng();
286
287 let path = [ChildNumber::Normal(32), ChildNumber::Normal(4)];
288
289 let private_key = PrivateKey::new(&mut rng);
290 let public_key = PublicKey::from_secret_key(&secp, &private_key);
291 let hd_private_key = ExtendedPrivateKey::new_master(private_key, [0; 32]);
292 let hd_public_key = ExtendedPublicKey::new_master(public_key, [0; 32]);
293
294 let new_hd_private_key = hd_private_key.derive_private_path(&secp, &path);
295 let new_hd_public_key = hd_public_key.derive_public_path(&secp, &path).unwrap();
296
297 assert_eq!(
298 PublicKey::from_secret_key(&secp, &new_hd_private_key.into_private_key()),
299 new_hd_public_key.into_public_key()
300 );
301 }
302
303 #[test]
304 fn child_derivation_normal_path_b() {
305 let secp = Secp256k1::new();
306 let mut rng = thread_rng();
307
308 let path = [
309 ChildNumber::Normal(32),
310 ChildNumber::Normal(4),
311 ChildNumber::Normal(54),
312 ];
313
314 let private_key = PrivateKey::new(&mut rng);
315 let hd_private_key = ExtendedPrivateKey::new_master(private_key, [0; 32]);
316
317 let hd_private_key_a = hd_private_key.derive_private_path(&secp, &path);
318 let hd_private_key_b = hd_private_key
319 .derive_private_child(&secp, path[0])
320 .derive_private_child(&secp, path[1])
321 .derive_private_child(&secp, path[2]);
322
323 assert_eq!(hd_private_key_a, hd_private_key_b);
324 }
325}