1use bip32::{PrivateKeyBytes, PublicKeyBytes};
2use primeorder::elliptic_curve::{
3 bigint::ArrayEncoding,
4 generic_array::{typenum::Unsigned, GenericArray},
5 ops::{MulByGenerator, ReduceNonZero},
6 sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
7 Curve, CurveArithmetic, NonZeroScalar, PublicKey, SecretKey,
8};
9
10use crate::prime_field::ReprSizeTypenum;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct PrivateKeyBip32<C: CurveArithmetic>(SecretKey<C>);
15
16impl<C: CurveArithmetic> From<SecretKey<C>> for PrivateKeyBip32<C> {
17 fn from(source: SecretKey<C>) -> Self {
18 Self(source)
19 }
20}
21
22impl<C: CurveArithmetic> AsRef<SecretKey<C>> for PrivateKeyBip32<C> {
23 fn as_ref(&self) -> &SecretKey<C> {
24 &self.0
25 }
26}
27
28impl<C: CurveArithmetic> From<PrivateKeyBip32<C>> for SecretKey<C> {
29 fn from(source: PrivateKeyBip32<C>) -> Self {
30 source.0
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub struct PublicKeyBip32<C: CurveArithmetic>(PublicKey<C>);
37
38impl<C: CurveArithmetic> From<PublicKey<C>> for PublicKeyBip32<C> {
39 fn from(source: PublicKey<C>) -> Self {
40 Self(source)
41 }
42}
43
44impl<C: CurveArithmetic> AsRef<PublicKey<C>> for PublicKeyBip32<C> {
45 fn as_ref(&self) -> &PublicKey<C> {
46 &self.0
47 }
48}
49
50impl<C: CurveArithmetic> From<PublicKeyBip32<C>> for PublicKey<C> {
51 fn from(source: PublicKeyBip32<C>) -> Self {
52 source.0
53 }
54}
55
56impl<C> bip32::PublicKey for PublicKeyBip32<C>
57where
58 C: Curve + CurveArithmetic,
59 C::AffinePoint: ToEncodedPoint<C> + FromEncodedPoint<C>,
60 C::FieldBytesSize: ModulusSize,
61 C::Scalar: ReduceNonZero<C::Uint>,
62{
63 fn from_bytes(bytes: PublicKeyBytes) -> Result<Self, bip32::Error> {
64 let bytes_len = bytes.len();
65 let ep =
66 EncodedPoint::<C>::from_bytes(&bytes[bytes_len - ReprSizeTypenum::to_usize() - 1..])
67 .map_err(|_| bip32::Error::Decode)?;
68 Ok(Self(
69 Option::from(PublicKey::from_encoded_point(&ep)).ok_or(bip32::Error::Crypto)?,
70 ))
71 }
72
73 fn to_bytes(&self) -> PublicKeyBytes {
74 let mut bytes = [0u8; 33];
75 let bytes_len = bytes.len();
76 let ep = self.0.to_encoded_point(true);
77 bytes[bytes_len - ReprSizeTypenum::to_usize() - 1..].copy_from_slice(ep.as_bytes());
78 bytes
79 }
80
81 fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, bip32::Error> {
82 let bytes_len = other.len();
83 let repr = GenericArray::<u8, <C::Uint as ArrayEncoding>::ByteSize>::from_exact_iter(
84 other[bytes_len - <C::Uint as ArrayEncoding>::ByteSize::to_usize()..]
85 .iter()
86 .copied(),
87 )
88 .expect("slice length is correct");
89 let child_scalar = NonZeroScalar::<C>::reduce_nonzero(C::Uint::from_be_byte_array(repr));
90
91 let child_point =
92 self.0.to_projective() + C::ProjectivePoint::mul_by_generator(&child_scalar);
93 Ok(Self(
94 PublicKey::from_affine(child_point.into()).map_err(|_| bip32::Error::Crypto)?,
95 ))
96 }
97}
98
99impl<C> bip32::PrivateKey for PrivateKeyBip32<C>
100where
101 C: Curve + CurveArithmetic,
102 C::AffinePoint: ToEncodedPoint<C> + FromEncodedPoint<C>,
103 C::FieldBytesSize: ModulusSize,
104 C::Scalar: ReduceNonZero<C::Uint>,
105{
106 type PublicKey = PublicKeyBip32<C>;
107
108 fn from_bytes(bytes: &PrivateKeyBytes) -> Result<Self, bip32::Error> {
109 let bytes_len = bytes.len();
110 Ok(Self(
111 SecretKey::from_slice(&bytes[bytes_len - ReprSizeTypenum::to_usize()..])
112 .map_err(|_| bip32::Error::Crypto)?,
113 ))
114 }
115
116 fn to_bytes(&self) -> PrivateKeyBytes {
117 let repr = self.0.to_bytes();
118 let mut bytes = PrivateKeyBytes::default();
119 let bytes_len = bytes.len();
120 bytes[bytes_len - repr.len()..].copy_from_slice(&repr);
121 bytes
122 }
123
124 fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, bip32::Error> {
125 let bytes_len = other.len();
126 let repr = GenericArray::<u8, <C::Uint as ArrayEncoding>::ByteSize>::from_exact_iter(
127 other[bytes_len - <C::Uint as ArrayEncoding>::ByteSize::to_usize()..]
128 .iter()
129 .copied(),
130 )
131 .expect("slice length is correct");
132 let child_scalar = NonZeroScalar::<C>::reduce_nonzero(C::Uint::from_be_byte_array(repr));
133 let derived_scalar = *self.0.to_nonzero_scalar().as_ref() + *child_scalar.as_ref();
134
135 Option::<NonZeroScalar<C>>::from(NonZeroScalar::new(derived_scalar))
136 .map(SecretKey::from)
137 .map(Self)
138 .ok_or(bip32::Error::Crypto)
139 }
140
141 fn public_key(&self) -> Self::PublicKey {
142 PublicKeyBip32(SecretKey::public_key(&self.0))
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use bip32::{ChildNumber, PrivateKey as _, PublicKey as _};
149 use primeorder::elliptic_curve::SecretKey;
150 use rand_core::OsRng;
151
152 use crate::curve64::TinyCurve64;
153
154 use super::{PrivateKeyBip32, PublicKeyBip32};
155
156 #[test]
157 fn public_key_roundtrip() {
158 let sk = SecretKey::<TinyCurve64>::random(&mut OsRng);
159 let pk = sk.public_key();
160
161 let pk_bip32 = PublicKeyBip32::from(pk);
162 let bytes = pk_bip32.to_bytes();
163 let pk_bip32_back = PublicKeyBip32::<TinyCurve64>::from_bytes(bytes).unwrap();
164 assert_eq!(pk_bip32, pk_bip32_back);
165 }
166
167 #[test]
168 fn private_key_roundtrip() {
169 let sk = SecretKey::<TinyCurve64>::random(&mut OsRng);
170
171 let sk_bip32 = PrivateKeyBip32::from(sk);
172 let bytes = sk_bip32.to_bytes();
173 let sk_bip32_back = PrivateKeyBip32::<TinyCurve64>::from_bytes(&bytes).unwrap();
174 assert_eq!(sk_bip32, sk_bip32_back);
175 }
176
177 #[test]
178 fn derivation() {
179 let sk = SecretKey::<TinyCurve64>::random(&mut OsRng);
180 let pk = sk.public_key();
181
182 let child_number = ChildNumber(123);
183 let chain_code = [1u8; 32];
184
185 let sk = PrivateKeyBip32::from(sk);
186 let pk = PublicKeyBip32::from(pk);
187
188 let (tweak, _new_chain_code) = pk.derive_tweak(&chain_code, child_number).unwrap();
189
190 let derived_from_sk = sk.derive_child(tweak).unwrap();
191 let derived_from_pk = pk.derive_child(tweak).unwrap();
192
193 assert_eq!(derived_from_sk.public_key(), derived_from_pk);
194 }
195}