1#![no_std]
2
3extern crate alloc;
4
5pub mod path;
6
7pub use crate::path::BIP32Path;
8
9use alloc::vec::Vec;
10use core::convert::TryInto;
11use core::fmt;
12
13use ed25519_dalek::{SigningKey, VerifyingKey};
14use hmac::{crypto_mac::Output, Hmac, Mac, NewMac};
15use sha2::Sha512;
16
17pub(crate) const HARDEND: u32 = 1 << 31;
18
19#[derive(Debug)]
20pub enum Error {
21 InvalidIndex,
22}
23
24impl fmt::Display for Error {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 match self {
27 Error::InvalidIndex => "Invalid index provided".fmt(f),
28 }
29 }
30}
31
32type HmacSha256 = Hmac<Sha512>;
36
37pub fn derive_key_from_path(seed: &[u8], curve: Curve, path: &BIP32Path) -> Result<Key, Error> {
39 let master: Result<Key, Error> = Ok(Key::new(seed, curve));
40
41 path.0.iter().fold(master, |key, index| match key {
42 Ok(k) => Ok(k.generate_child_key(*index)?),
43 Err(e) => Err(e),
44 })
45}
46
47#[derive(Clone, Copy, Debug)]
48pub enum Curve {
49 Ed25519,
50}
51
52impl Curve {
53 fn seedkey(&self) -> &[u8] {
54 match self {
55 Curve::Ed25519 => b"ed25519 seed",
56 }
57 }
58
59 fn validate_child_index(&self, index: u32) -> bool {
60 match self {
61 Curve::Ed25519 => index < HARDEND,
62 }
63 }
64
65 fn public_key(&self, key: &[u8; 32]) -> Vec<u8> {
66 match self {
67 Curve::Ed25519 => {
68 let signing_key: SigningKey = SigningKey::from_bytes(key);
69 let public: VerifyingKey = signing_key.verifying_key();
70 let mut result = Vec::new();
71 result.push(0);
72 public.to_bytes().iter().for_each(|i| result.push(*i));
73 result
74 }
75 }
76 }
77}
78
79pub struct Key {
81 pub key: [u8; 32],
82 pub chain_code: [u8; 32],
83 pub curve: Curve,
84}
85
86impl Key {
87 pub fn new(seed: &[u8], curve: Curve) -> Self {
89 let inter = hmac_sha256(curve.seedkey(), seed).into_bytes();
91
92 let key: [u8; 32] = inter[..32].try_into().unwrap();
95 let chain_code: [u8; 32] = inter[32..].try_into().unwrap();
96
97 Self {
98 key,
99 chain_code,
100 curve,
101 }
102 }
103
104 pub fn public_key(&self) -> [u8; 33] {
106 let mut key = [0u8; 33];
107 key.copy_from_slice(&self.curve.public_key(&self.key));
108 key
109 }
110
111 fn generate_child_key(&self, index: u32) -> Result<Key, Error> {
112 if self.curve.validate_child_index(index) {
113 return Err(Error::InvalidIndex);
114 }
115
116 let inter = self.get_intermediary(index).into_bytes();
117
118 let key: [u8; 32] = inter[..32].try_into().unwrap();
120 let chain_code: [u8; 32] = inter[32..].try_into().unwrap();
121
122 Ok(Key {
125 key,
126 chain_code,
127 curve: self.curve,
128 })
129 }
130
131 fn get_intermediary(&self, index: u32) -> Output<HmacSha256> {
132 let mut data = Vec::new();
133 if index < HARDEND {
134 data.append(&mut self.curve.public_key(&self.key));
135 } else {
136 data.push(0u8);
137 self.key.iter().for_each(|i| data.push(*i));
138 }
139 index.to_be_bytes().iter().for_each(|i| data.push(*i));
140
141 hmac_sha256(&self.chain_code, &data)
142 }
143}
144
145fn hmac_sha256(key: &[u8], data: &[u8]) -> Output<HmacSha256> {
146 let mut mac = HmacSha256::new_varkey(key).expect("HMAC can take key of any size");
148 mac.update(data);
149
150 mac.finalize()
153}