iop_keyvault/ed25519/
ext_sk.rs1use super::*;
2
3#[derive(Clone)]
5pub struct EdExtPrivateKey {
6 chain_code: ChainCode,
7 sk: EdPrivateKey,
8}
9
10impl EdExtPrivateKey {
11 pub fn chain_code(&self) -> &ChainCode {
13 &self.chain_code
14 }
15
16 pub(crate) fn cook_new<F: Fn(&mut HmacSha512)>(salt: &[u8], recipe: F) -> Self {
17 let mut hasher = <HmacSha512 as KeyInit>::new_from_slice(salt).unwrap();
20
21 recipe(&mut hasher);
22
23 let hash_bytes = hasher.finalize().into_bytes();
24
25 let sk_bytes = &hash_bytes[..PRIVATE_KEY_SIZE];
26 let cc_bytes = &hash_bytes[PRIVATE_KEY_SIZE..];
27
28 let chain_code = ChainCode::from_bytes(cc_bytes).unwrap();
29 let sk = EdPrivateKey::from_bytes(sk_bytes).unwrap();
30
31 Self { chain_code, sk }
32 }
33}
34
35impl ExtendedPrivateKey<Ed25519> for EdExtPrivateKey {
36 fn derive_normal_child(&self, _idx: i32) -> Result<EdExtPrivateKey> {
37 bail!("Normal derivation of Ed25519 is invalid based on SLIP-0010.")
38 }
39 fn derive_hardened_child(&self, idx: i32) -> Result<EdExtPrivateKey> {
43 ensure!(idx >= 0, "Derivation index cannot be negative");
44 let idx = idx as u32;
45
46 let xprv = EdExtPrivateKey::cook_new(&self.chain_code.to_bytes(), |hasher| {
47 hasher.update(&[0x00u8]);
48 hasher.update(&self.sk.to_bytes());
49 hasher.update(&(0x8000_0000u32 + idx).to_be_bytes());
50 });
51
52 Ok(xprv)
53 }
54 fn neuter(&self) -> EdPublicKey {
55 self.sk.public_key()
56 }
57 fn private_key(&self) -> EdPrivateKey {
58 self.sk.clone()
59 }
60}