Skip to content

Bug fix using same seed sequence for channel key geneartion #235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 1, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions src/chain/keysinterface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@ use secp256k1::Secp256k1;
use secp256k1;

use crypto::hkdf::{hkdf_extract,hkdf_expand};
use crypto::digest::Digest;

use util::sha2::Sha256;
use util::logger::Logger;
use util::rng;
use util::byte_utils;

use std::time::{SystemTime, UNIX_EPOCH};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

/// When on-chain outputs are created by rust-lightning an event is generated which informs the
/// user thereof. This enum describes the format of the output and provides the OutPoint.
Expand All @@ -39,7 +44,7 @@ pub enum SpendableOutputDescriptor {
DynamicOutput {
/// Outpoint spendable by user wallet
outpoint: OutPoint,
/// local_delayedkey = delayed_payment_basepoint_secret + SHA256(per_commitment_point || delayed_payment_basepoint
/// local_delayedkey = delayed_payment_basepoint_secret + SHA256(per_commitment_point || delayed_payment_basepoint)
local_delayedkey: SecretKey,
/// witness redeemScript encumbering output
witness_script: Script,
Expand Down Expand Up @@ -137,6 +142,7 @@ pub struct KeysManager {
destination_script: Script,
shutdown_pubkey: PublicKey,
channel_master_key: ExtendedPrivKey,
channel_child_index: AtomicUsize,

logger: Arc<Logger>,
}
Expand Down Expand Up @@ -169,6 +175,7 @@ impl KeysManager {
destination_script,
shutdown_pubkey,
channel_master_key,
channel_child_index: AtomicUsize::new(0),

logger,
}
Expand All @@ -192,11 +199,25 @@ impl KeysInterface for KeysManager {
}

fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys {
let channel_pubkey = ExtendedPubKey::from_private(&self.secp_ctx, &self. channel_master_key);
let mut seed = [0; 32];
for (arr, slice) in seed.iter_mut().zip((&channel_pubkey.public_key.serialize()[0..32]).iter()) {
*arr = *slice;
}
// We only seriously intend to rely on the channel_master_key for true secure
// entropy, everything else just ensures uniqueness. We generally don't expect
// all clients to have non-broken RNGs here, so we also include the current
// time as a fallback to get uniqueness.
let mut sha = Sha256::new();

let mut seed = [0u8; 32];
rng::fill_bytes(&mut seed[..]);
sha.input(&seed);

let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards");
sha.input(&byte_utils::be32_to_array(now.subsec_nanos()));
sha.input(&byte_utils::be64_to_array(now.as_secs()));

let child_ix = self.channel_child_index.fetch_add(1, Ordering::AcqRel);
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");
sha.input(&child_privkey.secret_key[..]);

sha.result(&mut seed);
ChannelKeys::new_from_seed(&seed)
}
}