@@ -6,7 +6,7 @@ use bitcoin::blockdata::transaction::{OutPoint, TxOut};
6
6
use bitcoin:: blockdata:: script:: { Script , Builder } ;
7
7
use bitcoin:: blockdata:: opcodes;
8
8
use bitcoin:: network:: constants:: Network ;
9
- use bitcoin:: util:: hash:: Hash160 ;
9
+ use bitcoin:: util:: hash:: { Hash160 , Sha256dHash } ;
10
10
use bitcoin:: util:: bip32:: { ExtendedPrivKey , ExtendedPubKey , ChildNumber } ;
11
11
12
12
use secp256k1:: key:: { SecretKey , PublicKey } ;
@@ -17,8 +17,12 @@ use crypto::hkdf::{hkdf_extract,hkdf_expand};
17
17
18
18
use util:: sha2:: Sha256 ;
19
19
use util:: logger:: Logger ;
20
+ use util:: rng;
21
+ use util:: byte_utils;
20
22
23
+ use std:: time:: { SystemTime , UNIX_EPOCH } ;
21
24
use std:: sync:: Arc ;
25
+ use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
22
26
23
27
/// When on-chain outputs are created by rust-lightning an event is generated which informs the
24
28
/// user thereof. This enum describes the format of the output and provides the OutPoint.
@@ -39,7 +43,7 @@ pub enum SpendableOutputDescriptor {
39
43
DynamicOutput {
40
44
/// Outpoint spendable by user wallet
41
45
outpoint : OutPoint ,
42
- /// local_delayedkey = delayed_payment_basepoint_secret + SHA256(per_commitment_point || delayed_payment_basepoint
46
+ /// local_delayedkey = delayed_payment_basepoint_secret + SHA256(per_commitment_point || delayed_payment_basepoint)
43
47
local_delayedkey : SecretKey ,
44
48
/// witness redeemScript encumbering output
45
49
witness_script : Script ,
@@ -137,6 +141,7 @@ pub struct KeysManager {
137
141
destination_script : Script ,
138
142
shutdown_pubkey : PublicKey ,
139
143
channel_master_key : ExtendedPrivKey ,
144
+ channel_child_index : AtomicUsize ,
140
145
141
146
logger : Arc < Logger > ,
142
147
}
@@ -169,6 +174,7 @@ impl KeysManager {
169
174
destination_script,
170
175
shutdown_pubkey,
171
176
channel_master_key,
177
+ channel_child_index : AtomicUsize :: new ( 0 ) ,
172
178
173
179
logger,
174
180
}
@@ -192,11 +198,18 @@ impl KeysInterface for KeysManager {
192
198
}
193
199
194
200
fn get_channel_keys ( & self , _inbound : bool ) -> ChannelKeys {
195
- let channel_pubkey = ExtendedPubKey :: from_private ( & self . secp_ctx , & self . channel_master_key ) ;
196
- let mut seed = [ 0 ; 32 ] ;
197
- for ( arr, slice) in seed. iter_mut ( ) . zip ( ( & channel_pubkey. public_key . serialize ( ) [ 0 ..32 ] ) . iter ( ) ) {
198
- * arr = * slice;
199
- }
200
- ChannelKeys :: new_from_seed ( & seed)
201
+ // We only seriously intend to rely on the channel_master_key for true secure entropy,
202
+ // everything else just ensures uniqueness. We generally don't expect all clients
203
+ // to have non-broken RNGs here, so we also include the current time as a fallback to get uniqueness."
204
+ let mut seed = [ 0u8 ; 32 + 4 + 8 + 32 ] ;
205
+ rng:: fill_bytes ( & mut seed[ ..32 ] ) ;
206
+ let now = SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . expect ( "Time went backwards" ) ;
207
+ seed[ 32 ..32 +4 ] . copy_from_slice ( & byte_utils:: be32_to_array ( now. subsec_nanos ( ) ) ) ;
208
+ seed[ 32 +4 ..32 +4 +8 ] . copy_from_slice ( & byte_utils:: be64_to_array ( now. as_secs ( ) ) ) ;
209
+
210
+ let child_ix = self . channel_child_index . fetch_add ( 1 , Ordering :: AcqRel ) ;
211
+ let child_privkey = self . channel_master_key . ckd_priv ( & self . secp_ctx , ChildNumber :: from_hardened_idx ( child_ix as u32 ) ) . expect ( "Your RNG is busted" ) ;
212
+ seed[ 32 +4 +8 ..32 +4 +8 +32 ] . copy_from_slice ( & child_privkey. secret_key [ ..32 ] ) ;
213
+ ChannelKeys :: new_from_seed ( & Sha256dHash :: from_data ( & seed) . as_bytes ( ) )
201
214
}
202
215
}
0 commit comments