11//! Extended private key operations according to BIP-32
2- use core:: convert:: TryInto ;
3-
42use super :: {
53 derivation_path:: { ChildIndex , ChildIndexError , DerivationPath } ,
64 ext_pub_key:: ExtPubKey ,
@@ -28,14 +26,23 @@ type HmacSha512 = Hmac<Sha512>;
2826
2927/// Extended secret key
3028/// implemented according to BIP-32
31- #[ derive( PartialEq , Eq , Debug , Clone ) ]
29+ #[ derive( PartialEq , Eq , Clone ) ]
3230pub struct ExtSecretKey {
33- /// The secret key
34- private_input : DlogProverInput ,
31+ private_input : Wscalar ,
3532 chain_code : ChainCode ,
3633 derivation_path : DerivationPath ,
3734}
3835
36+ impl core:: fmt:: Debug for ExtSecretKey {
37+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
38+ f. debug_struct ( "ExtSecretKey" )
39+ . field ( "private_input" , & "*****" ) // disable debug output for secret key to prevent key leakage in logs
40+ . field ( "chain_code" , & self . chain_code )
41+ . field ( "derivation_path" , & self . derivation_path )
42+ . finish ( )
43+ }
44+ }
45+
3946/// Extended secret key errors
4047#[ derive( Error , PartialEq , Eq , Debug , Clone ) ]
4148pub enum ExtSecretKeyError {
@@ -66,8 +73,8 @@ impl ExtSecretKey {
6673 chain_code : ChainCode ,
6774 derivation_path : DerivationPath ,
6875 ) -> Result < Self , ExtSecretKeyError > {
69- let private_input = DlogProverInput :: from_bytes ( & secret_key_bytes )
70- . ok_or ( ExtSecretKeyError :: ScalarEncodingError ) ?;
76+ let private_input =
77+ Wscalar :: from_bytes ( & secret_key_bytes ) . ok_or ( ExtSecretKeyError :: ScalarEncodingError ) ?;
7178 Ok ( Self {
7279 private_input,
7380 chain_code,
@@ -82,7 +89,7 @@ impl ExtSecretKey {
8289
8390 /// Returns secret key
8491 pub fn secret_key ( & self ) -> SecretKey {
85- self . private_input . clone ( ) . into ( )
92+ DlogProverInput :: new ( self . private_input . clone ( ) ) . into ( )
8693 }
8794
8895 /// Byte representation of the underlying scalar
@@ -92,7 +99,7 @@ impl ExtSecretKey {
9299
93100 /// Public image associated with the private input
94101 pub fn public_image ( & self ) -> ProveDlog {
95- self . private_input . public_image ( )
102+ DlogProverInput :: new ( self . private_input . clone ( ) ) . public_image ( )
96103 }
97104
98105 /// Public image bytes in SEC-1 encoded & compressed format
@@ -103,12 +110,11 @@ impl ExtSecretKey {
103110 /// The extended public key associated with this secret key
104111 pub fn public_key ( & self ) -> Result < ExtPubKey , ExtSecretKeyError > {
105112 #[ allow( clippy:: unwrap_used) ]
106- Ok ( ExtPubKey :: new (
107- // unwrap is safe as it is used on an Infallible result type
108- self . public_image_bytes ( ) ?. try_into ( ) . unwrap ( ) ,
109- self . chain_code ,
110- self . derivation_path . clone ( ) ,
111- ) ?)
113+ Ok ( ExtPubKey {
114+ public_key : * self . public_image ( ) . h ,
115+ chain_code : self . chain_code ,
116+ derivation_path : self . derivation_path . clone ( ) ,
117+ } )
112118 }
113119
114120 /// Derive a child extended secret key using the provided index
@@ -127,16 +133,14 @@ impl ExtSecretKey {
127133 let mac_bytes = mac. finalize ( ) . into_bytes ( ) ;
128134 let mut secret_key_bytes = [ 0 ; SecretKeyBytes :: LEN ] ;
129135 secret_key_bytes. copy_from_slice ( & mac_bytes[ ..32 ] ) ;
130- if let Some ( dlog_prover ) = DlogProverInput :: from_bytes ( & secret_key_bytes) {
136+ if let Some ( wscalar ) = Wscalar :: from_bytes ( & secret_key_bytes) {
131137 // parse256(IL) + kpar (mod n).
132138 // via https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions
133- let child_secret_key: DlogProverInput = Wscalar :: from (
134- dlog_prover
135- . w
139+ let child_secret_key = Wscalar :: from (
140+ wscalar
136141 . as_scalar_ref ( )
137- . add ( self . private_input . w . as_scalar_ref ( ) ) ,
138- )
139- . into ( ) ;
142+ . add ( self . private_input . as_scalar_ref ( ) ) ,
143+ ) ;
140144 if child_secret_key. is_zero ( ) {
141145 // ki == 0 case of:
142146 // > In case parse256(IL) ≥ n or ki = 0, the resulting key is invalid, and one
0 commit comments