X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fkeysinterface.rs;h=3ccab2ce9dabb0b36f9876210a1d39bd5faff98d;hb=0517b18a01cc3b1bad9b7101e400055656da44db;hp=21331fff435e601a255a6944c04a8fff820db0bc;hpb=fac5373687a4c7919c8639744dc712d922082cc3;p=rust-lightning diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 21331fff..3ccab2ce 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -32,11 +32,11 @@ use bitcoin::secp256k1::ecdsa::RecoverableSignature; use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness}; use crate::util::transaction_utils; -use crate::util::crypto::{hkdf_extract_expand_twice, sign}; -use crate::util::ser::{Writeable, Writer, Readable}; -#[cfg(anchors)] -use crate::util::events::HTLCDescriptor; +use crate::util::crypto::{hkdf_extract_expand_twice, sign, sign_with_aux_rand}; +use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs}; use crate::chain::transaction::OutPoint; +#[cfg(anchors)] +use crate::events::bump_transaction::HTLCDescriptor; use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; use crate::ln::{chan_utils, PaymentPreimage}; use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction}; @@ -45,6 +45,7 @@ use crate::ln::script::ShutdownScript; use crate::prelude::*; use core::convert::TryInto; +use core::ops::Deref; use core::sync::atomic::{AtomicUsize, Ordering}; use crate::io::{self, Error}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; @@ -55,7 +56,7 @@ use crate::util::invoice::construct_invoice_preimage; /// Used as initial key material, to be expanded into multiple secret keys (but not to be used /// directly). This is used within LDK to encrypt/decrypt inbound payment data. /// -/// (C-not exported) as we just use `[u8; 32]` directly +/// This is not exported to bindings users as we just use `[u8; 32]` directly #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)] pub struct KeyMaterial(pub [u8; 32]); @@ -84,6 +85,8 @@ pub struct DelayedPaymentOutputDescriptor { } impl DelayedPaymentOutputDescriptor { /// The maximum length a well-formed witness spending one of these should have. + /// Note: If you have the grind_signatures feature enabled, this will be at least 1 byte + /// shorter. // Calculated as 1 byte length + 73 byte signature, 1 byte empty vec push, 1 byte length plus // redeemscript push length. pub const MAX_WITNESS_LENGTH: usize = 1 + 73 + 1 + chan_utils::REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH + 1; @@ -116,6 +119,8 @@ pub struct StaticPaymentOutputDescriptor { } impl StaticPaymentOutputDescriptor { /// The maximum length a well-formed witness spending one of these should have. + /// Note: If you have the grind_signatures feature enabled, this will be at least 1 byte + /// shorter. // Calculated as 1 byte legnth + 73 byte signature, 1 byte empty vec push, 1 byte length plus // redeemscript push length. pub const MAX_WITNESS_LENGTH: usize = 1 + 73 + 34; @@ -135,7 +140,7 @@ impl_writeable_tlv_based!(StaticPaymentOutputDescriptor, { /// outpoint describing which `txid` and output `index` is available, the full output which exists /// at that `txid`/`index`, and any keys or other information required to sign. /// -/// [`SpendableOutputs`]: crate::util::events::Event::SpendableOutputs +/// [`SpendableOutputs`]: crate::events::Event::SpendableOutputs #[derive(Clone, Debug, PartialEq, Eq)] pub enum SpendableOutputDescriptor { /// An output to a script which was provided via [`SignerProvider`] directly, either from @@ -553,7 +558,6 @@ pub trait SignerProvider { fn get_shutdown_scriptpubkey(&self) -> ShutdownScript; } -#[derive(Clone)] /// A simple implementation of [`WriteableEcdsaChannelSigner`] that just keeps the private keys in memory. /// /// This implementation performs no policy checks and is insufficient by itself as @@ -580,6 +584,30 @@ pub struct InMemorySigner { channel_value_satoshis: u64, /// Key derivation parameters. channel_keys_id: [u8; 32], + /// Seed from which all randomness produced is derived from. + rand_bytes_unique_start: [u8; 32], + /// Tracks the number of times we've produced randomness to ensure we don't return the same + /// bytes twice. + rand_bytes_index: AtomicCounter, +} + +impl Clone for InMemorySigner { + fn clone(&self) -> Self { + Self { + funding_key: self.funding_key.clone(), + revocation_base_key: self.revocation_base_key.clone(), + payment_key: self.payment_key.clone(), + delayed_payment_base_key: self.delayed_payment_base_key.clone(), + htlc_base_key: self.htlc_base_key.clone(), + commitment_seed: self.commitment_seed.clone(), + holder_channel_pubkeys: self.holder_channel_pubkeys.clone(), + channel_parameters: self.channel_parameters.clone(), + channel_value_satoshis: self.channel_value_satoshis, + channel_keys_id: self.channel_keys_id, + rand_bytes_unique_start: self.get_secure_random_bytes(), + rand_bytes_index: AtomicCounter::new(), + } + } } impl InMemorySigner { @@ -594,6 +622,7 @@ impl InMemorySigner { commitment_seed: [u8; 32], channel_value_satoshis: u64, channel_keys_id: [u8; 32], + rand_bytes_unique_start: [u8; 32], ) -> InMemorySigner { let holder_channel_pubkeys = InMemorySigner::make_holder_keys(secp_ctx, &funding_key, &revocation_base_key, @@ -610,6 +639,8 @@ impl InMemorySigner { holder_channel_pubkeys, channel_parameters: None, channel_keys_id, + rand_bytes_unique_start, + rand_bytes_index: AtomicCounter::new(), } } @@ -686,7 +717,7 @@ impl InMemorySigner { let remotepubkey = self.pubkeys().payment_point; let witness_script = bitcoin::Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: remotepubkey}, Network::Testnet).script_pubkey(); let sighash = hash_to_message!(&sighash::SighashCache::new(spend_tx).segwit_signature_hash(input_idx, &witness_script, descriptor.output.value, EcdsaSighashType::All).unwrap()[..]); - let remotesig = sign(secp_ctx, &sighash, &self.payment_key); + let remotesig = sign_with_aux_rand(secp_ctx, &sighash, &self.payment_key, &self); let payment_script = bitcoin::Address::p2wpkh(&::bitcoin::PublicKey{compressed: true, inner: remotepubkey}, Network::Bitcoin).unwrap().script_pubkey(); if payment_script != descriptor.output.script_pubkey { return Err(()); } @@ -722,7 +753,7 @@ impl InMemorySigner { let delayed_payment_pubkey = PublicKey::from_secret_key(&secp_ctx, &delayed_payment_key); let witness_script = chan_utils::get_revokeable_redeemscript(&descriptor.revocation_pubkey, descriptor.to_self_delay, &delayed_payment_pubkey); let sighash = hash_to_message!(&sighash::SighashCache::new(spend_tx).segwit_signature_hash(input_idx, &witness_script, descriptor.output.value, EcdsaSighashType::All).unwrap()[..]); - let local_delayedsig = sign(secp_ctx, &sighash, &delayed_payment_key); + let local_delayedsig = sign_with_aux_rand(secp_ctx, &sighash, &delayed_payment_key, &self); let payment_script = bitcoin::Address::p2wsh(&witness_script, Network::Bitcoin).script_pubkey(); if descriptor.output.script_pubkey != payment_script { return Err(()); } @@ -736,6 +767,15 @@ impl InMemorySigner { } } +impl EntropySource for InMemorySigner { + fn get_secure_random_bytes(&self) -> [u8; 32] { + let index = self.rand_bytes_index.get_increment(); + let mut nonce = [0u8; 16]; + nonce[..8].copy_from_slice(&index.to_be_bytes()); + ChaCha20::get_single_block(&self.rand_bytes_unique_start, &nonce) + } +} + impl ChannelSigner for InMemorySigner { fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) -> PublicKey { let commitment_secret = SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx)).unwrap(); @@ -774,7 +814,7 @@ impl EcdsaChannelSigner for InMemorySigner { let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey); let built_tx = trusted_tx.built_transaction(); - let commitment_sig = built_tx.sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx); + let commitment_sig = built_tx.sign_counterparty_commitment(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx); let commitment_txid = built_tx.txid; let mut htlc_sigs = Vec::with_capacity(commitment_tx.htlcs().len()); @@ -799,9 +839,9 @@ impl EcdsaChannelSigner for InMemorySigner { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey); let trusted_tx = commitment_tx.trust(); - let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx); + let sig = trusted_tx.built_transaction().sign_holder_commitment(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, &self, secp_ctx); let channel_parameters = self.get_channel_parameters(); - let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?; + let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), &self, secp_ctx)?; Ok((sig, htlc_sigs)) } @@ -810,9 +850,9 @@ impl EcdsaChannelSigner for InMemorySigner { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey); let trusted_tx = commitment_tx.trust(); - let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx); + let sig = trusted_tx.built_transaction().sign_holder_commitment(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, &self, secp_ctx); let channel_parameters = self.get_channel_parameters(); - let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?; + let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), &self, secp_ctx)?; Ok((sig, htlc_sigs)) } @@ -826,7 +866,7 @@ impl EcdsaChannelSigner for InMemorySigner { }; let mut sighash_parts = sighash::SighashCache::new(justice_tx); let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - return Ok(sign(secp_ctx, &sighash, &revocation_key)) + return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)) } fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { @@ -840,7 +880,7 @@ impl EcdsaChannelSigner for InMemorySigner { }; let mut sighash_parts = sighash::SighashCache::new(justice_tx); let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - return Ok(sign(secp_ctx, &sighash, &revocation_key)) + return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)) } #[cfg(anchors)] @@ -858,7 +898,7 @@ impl EcdsaChannelSigner for InMemorySigner { let our_htlc_private_key = chan_utils::derive_private_key( &secp_ctx, &per_commitment_point, &self.htlc_base_key ); - Ok(sign(&secp_ctx, &hash_to_message!(sighash), &our_htlc_private_key)) + Ok(sign_with_aux_rand(&secp_ctx, &hash_to_message!(sighash), &our_htlc_private_key, &self)) } fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { @@ -869,7 +909,7 @@ impl EcdsaChannelSigner for InMemorySigner { let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, self.opt_anchors(), &counterparty_htlcpubkey, &htlcpubkey, &revocation_pubkey); let mut sighash_parts = sighash::SighashCache::new(htlc_tx); let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - Ok(sign(secp_ctx, &sighash, &htlc_key)) + Ok(sign_with_aux_rand(secp_ctx, &sighash, &htlc_key, &self)) } fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { @@ -885,14 +925,14 @@ impl EcdsaChannelSigner for InMemorySigner { let sighash = sighash::SighashCache::new(&*anchor_tx).segwit_signature_hash( input, &witness_script, ANCHOR_OUTPUT_VALUE_SATOSHI, EcdsaSighashType::All, ).unwrap(); - Ok(sign(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key)) + Ok(sign_with_aux_rand(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key, &self)) } fn sign_channel_announcement_with_funding_key( &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 ) -> Result { let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - Ok(sign(secp_ctx, &msghash, &self.funding_key)) + Ok(secp_ctx.sign_ecdsa(&msghash, &self.funding_key)) } } @@ -922,8 +962,8 @@ impl Writeable for InMemorySigner { } } -impl Readable for InMemorySigner { - fn read(reader: &mut R) -> Result { +impl ReadableArgs for InMemorySigner where ES::Target: EntropySource { + fn read(reader: &mut R, entropy_source: ES) -> Result { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let funding_key = Readable::read(reader)?; @@ -953,6 +993,8 @@ impl Readable for InMemorySigner { holder_channel_pubkeys, channel_parameters: counterparty_channel_data, channel_keys_id: keys_id, + rand_bytes_unique_start: entropy_source.get_secure_random_bytes(), + rand_bytes_index: AtomicCounter::new(), }) } } @@ -1107,6 +1149,7 @@ impl KeysManager { let payment_key = key_step!(b"payment key", revocation_base_key); let delayed_payment_base_key = key_step!(b"delayed payment base key", payment_key); let htlc_base_key = key_step!(b"HTLC base key", delayed_payment_base_key); + let prng_seed = self.get_secure_random_bytes(); InMemorySigner::new( &self.secp_ctx, @@ -1118,6 +1161,7 @@ impl KeysManager { commitment_seed, channel_value_satoshis, params.clone(), + prng_seed, ) } @@ -1148,6 +1192,8 @@ impl KeysManager { witness: Witness::new(), }); witness_weight += StaticPaymentOutputDescriptor::MAX_WITNESS_LENGTH; + #[cfg(feature = "grind_signatures")] + { witness_weight -= 1; } // Guarantees a low R signature input_value += descriptor.output.value; if !output_set.insert(descriptor.outpoint) { return Err(()); } }, @@ -1159,6 +1205,8 @@ impl KeysManager { witness: Witness::new(), }); witness_weight += DelayedPaymentOutputDescriptor::MAX_WITNESS_LENGTH; + #[cfg(feature = "grind_signatures")] + { witness_weight -= 1; } // Guarantees a low R signature input_value += descriptor.output.value; if !output_set.insert(descriptor.outpoint) { return Err(()); } }, @@ -1170,6 +1218,8 @@ impl KeysManager { witness: Witness::new(), }); witness_weight += 1 + 73 + 34; + #[cfg(feature = "grind_signatures")] + { witness_weight -= 1; } // Guarantees a low R signature input_value += output.value; if !output_set.insert(*outpoint) { return Err(()); } } @@ -1233,7 +1283,7 @@ impl KeysManager { if payment_script != output.script_pubkey { return Err(()); }; let sighash = hash_to_message!(&sighash::SighashCache::new(&spend_tx).segwit_signature_hash(input_idx, &witness_script, output.value, EcdsaSighashType::All).unwrap()[..]); - let sig = sign(secp_ctx, &sighash, &secret.private_key); + let sig = sign_with_aux_rand(secp_ctx, &sighash, &secret.private_key, &self); let mut sig_ser = sig.serialize_der().to_vec(); sig_ser.push(EcdsaSighashType::All as u8); spend_tx.input[input_idx].witness.push(sig_ser); @@ -1295,7 +1345,7 @@ impl NodeSigner for KeysManager { fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result { let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - Ok(sign(&self.secp_ctx, &msg_hash, &self.node_secret)) + Ok(self.secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret)) } } @@ -1323,7 +1373,7 @@ impl SignerProvider for KeysManager { } fn read_chan_signer(&self, reader: &[u8]) -> Result { - InMemorySigner::read(&mut io::Cursor::new(reader)) + InMemorySigner::read(&mut io::Cursor::new(reader), self) } fn get_destination_script(&self) -> Script {