tiny_curve/
bip32.rs

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/// A newtype wrapper for [`elliptic_curve::SecretKey`] implementing [`bip32`] traits.
13#[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/// A newtype wrapper for [`elliptic_curve::PublicKey`] implementing [`bip32`] traits.
35#[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}