1use crate::{ChainCode, ChildNumber, Error, HmacSha512, PublicKey, Result, KEY_SIZE};
4use hmac::Mac;
5
6#[cfg(feature = "secp256k1")]
7use crate::XPrv;
8
9pub type PrivateKeyBytes = [u8; KEY_SIZE];
11
12pub trait PrivateKey: Sized {
14 type PublicKey: PublicKey;
16
17 fn from_bytes(bytes: &PrivateKeyBytes) -> Result<Self>;
19
20 fn to_bytes(&self) -> PrivateKeyBytes;
22
23 fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self>;
27
28 fn public_key(&self) -> Self::PublicKey;
30
31 fn derive_tweak(
41 &self,
42 chain_code: &ChainCode,
43 child_number: ChildNumber,
44 ) -> Result<(PrivateKeyBytes, ChainCode)> {
45 let mut hmac = HmacSha512::new_from_slice(chain_code).map_err(|_| Error::Crypto)?;
46
47 if child_number.is_hardened() {
48 hmac.update(&[0]);
49 hmac.update(&self.to_bytes());
50 } else {
51 hmac.update(&self.public_key().to_bytes());
52 }
53
54 hmac.update(&child_number.to_bytes());
55
56 let result = hmac.finalize().into_bytes();
57 let (tweak_bytes, chain_code_bytes) = result.split_at(KEY_SIZE);
58
59 let tweak = tweak_bytes.try_into()?;
62
63 let chain_code = chain_code_bytes.try_into()?;
64
65 Ok((tweak, chain_code))
66 }
67}
68
69#[cfg(feature = "secp256k1")]
70impl PrivateKey for k256::SecretKey {
71 type PublicKey = k256::PublicKey;
72
73 fn from_bytes(bytes: &PrivateKeyBytes) -> Result<Self> {
74 Ok(k256::SecretKey::from_slice(bytes)?)
75 }
76
77 fn to_bytes(&self) -> PrivateKeyBytes {
78 k256::SecretKey::to_bytes(self).into()
79 }
80
81 fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self> {
82 let child_scalar =
83 Option::<k256::NonZeroScalar>::from(k256::NonZeroScalar::from_repr(other.into()))
84 .ok_or(Error::Crypto)?;
85
86 let derived_scalar = self.to_nonzero_scalar().as_ref() + child_scalar.as_ref();
87
88 Option::<k256::NonZeroScalar>::from(k256::NonZeroScalar::new(derived_scalar))
89 .map(Into::into)
90 .ok_or(Error::Crypto)
91 }
92
93 fn public_key(&self) -> Self::PublicKey {
94 k256::SecretKey::public_key(self)
95 }
96}
97
98#[cfg(feature = "secp256k1")]
99impl PrivateKey for k256::ecdsa::SigningKey {
100 type PublicKey = k256::ecdsa::VerifyingKey;
101
102 fn from_bytes(bytes: &PrivateKeyBytes) -> Result<Self> {
103 Ok(k256::ecdsa::SigningKey::from_slice(bytes)?)
104 }
105
106 fn to_bytes(&self) -> PrivateKeyBytes {
107 k256::ecdsa::SigningKey::to_bytes(self).into()
108 }
109
110 fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self> {
111 k256::SecretKey::from(self)
112 .derive_child(other)
113 .map(Into::into)
114 }
115
116 fn public_key(&self) -> Self::PublicKey {
117 *self.verifying_key()
118 }
119}
120
121#[cfg(feature = "secp256k1")]
122impl From<XPrv> for k256::ecdsa::SigningKey {
123 fn from(xprv: XPrv) -> k256::ecdsa::SigningKey {
124 k256::ecdsa::SigningKey::from(&xprv)
125 }
126}
127
128#[cfg(feature = "secp256k1")]
129impl From<&XPrv> for k256::ecdsa::SigningKey {
130 fn from(xprv: &XPrv) -> k256::ecdsa::SigningKey {
131 xprv.private_key().clone()
132 }
133}
134
135#[cfg(feature = "secp256k1-ffi")]
136impl PrivateKey for secp256k1_ffi::SecretKey {
137 type PublicKey = secp256k1_ffi::PublicKey;
138
139 fn from_bytes(bytes: &PrivateKeyBytes) -> Result<Self> {
140 Ok(secp256k1_ffi::SecretKey::from_slice(bytes)?)
141 }
142
143 fn to_bytes(&self) -> PrivateKeyBytes {
144 *self.as_ref()
145 }
146
147 fn derive_child(&self, bytes: PrivateKeyBytes) -> Result<Self> {
148 let scalar = secp256k1_ffi::Scalar::from_be_bytes(bytes)?;
149 Ok(self.add_tweak(&scalar)?)
150 }
151
152 fn public_key(&self) -> Self::PublicKey {
153 use secp256k1_ffi::{Secp256k1, SignOnly};
154 let engine = Secp256k1::<SignOnly>::signing_only();
155 secp256k1_ffi::PublicKey::from_secret_key(&engine, self)
156 }
157}
158
159#[cfg(all(test, feature = "bip39", feature = "secp256k1-ffi"))]
161mod tests {
162 use hex_literal::hex;
163
164 type XPrv = crate::ExtendedPrivateKey<secp256k1_ffi::SecretKey>;
165
166 #[test]
167 fn secp256k1_ffi_derivation() {
168 let seed = hex!(
169 "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a2
170 9f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"
171 );
172
173 let path = "m/0/2147483647'/1/2147483646'/2";
174 let xprv = XPrv::derive_from_path(&seed, &path.parse().unwrap()).unwrap();
175
176 assert_eq!(
177 xprv,
178 "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j".parse().unwrap()
179 );
180 }
181}