X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fblinded_path%2Futils.rs;h=7ddb39c1b68fbce0a93fca0637e604b70b393b90;hb=3eec5d3c17ec5d251f5f8ac6533e39e769eaf3f1;hp=1993ad932267db8f2d2c8a98f999f2726530b833;hpb=f1761e06e6b44cedb1e1a9886b96c6723cdad2f3;p=rust-lightning diff --git a/lightning/src/blinded_path/utils.rs b/lightning/src/blinded_path/utils.rs index 1993ad93..7ddb39c1 100644 --- a/lightning/src/blinded_path/utils.rs +++ b/lightning/src/blinded_path/utils.rs @@ -15,19 +15,27 @@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey, Scalar}; use bitcoin::secp256k1::ecdh::SharedSecret; -use super::BlindedPath; +use super::{BlindedHop, BlindedPath}; +use crate::ln::msgs::DecodeError; use crate::ln::onion_utils; -use crate::onion_message::Destination; +use crate::onion_message::messenger::Destination; +use crate::util::chacha20poly1305rfc::ChaChaPolyWriteAdapter; +use crate::util::ser::{Readable, Writeable}; +use crate::io; use crate::prelude::*; // TODO: DRY with onion_utils::construct_onion_keys_callback #[inline] -pub(crate) fn construct_keys_callback, Option>)>( - secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], destination: Option, - session_priv: &SecretKey, mut callback: FType -) -> Result<(), secp256k1::Error> { +pub(crate) fn construct_keys_callback<'a, T, I, F>( + secp_ctx: &Secp256k1, unblinded_path: I, destination: Option, + session_priv: &SecretKey, mut callback: F +) -> Result<(), secp256k1::Error> +where + T: secp256k1::Signing + secp256k1::Verification, + I: Iterator, + F: FnMut(PublicKey, SharedSecret, PublicKey, [u8; 32], Option, Option>), +{ let mut msg_blinding_point_priv = session_priv.clone(); let mut msg_blinding_point = PublicKey::from_secret_key(secp_ctx, &msg_blinding_point_priv); let mut onion_packet_pubkey_priv = msg_blinding_point_priv.clone(); @@ -41,7 +49,7 @@ pub(crate) fn construct_keys_callback::new(b"blinded_node_id"); hmac.input(encrypted_data_ss.as_ref()); - Hmac::from_engine(hmac).into_inner() + Hmac::from_engine(hmac).to_byte_array() }; $pk.mul_tweak(secp_ctx, &Scalar::from_be_bytes(hop_pk_blinding_factor).unwrap())? }; @@ -62,7 +70,7 @@ pub(crate) fn construct_keys_callback( + secp_ctx: &Secp256k1, unblinded_pks: I1, mut unblinded_tlvs: I2, session_priv: &SecretKey +) -> Result, secp256k1::Error> +where + T: secp256k1::Signing + secp256k1::Verification, + I1: Iterator, + I2: Iterator, + I2::Item: Writeable +{ + let mut blinded_hops = Vec::with_capacity(unblinded_pks.size_hint().0); + construct_keys_callback( + secp_ctx, unblinded_pks, None, session_priv, + |blinded_node_id, _, _, encrypted_payload_rho, _, _| { + blinded_hops.push(BlindedHop { + blinded_node_id, + encrypted_payload: encrypt_payload(unblinded_tlvs.next().unwrap(), encrypted_payload_rho), + }); + })?; + Ok(blinded_hops) +} + +/// Encrypt TLV payload to be used as a [`crate::blinded_path::BlindedHop::encrypted_payload`]. +fn encrypt_payload(payload: P, encrypted_tlvs_rho: [u8; 32]) -> Vec { + let write_adapter = ChaChaPolyWriteAdapter::new(encrypted_tlvs_rho, &payload); + write_adapter.encode() +} + +/// Blinded path encrypted payloads may be padded to ensure they are equal length. +/// +/// Reads padding to the end, ignoring what's read. +pub(crate) struct Padding {} +impl Readable for Padding { + #[inline] + fn read(reader: &mut R) -> Result { + loop { + let mut buf = [0; 8192]; + if reader.read(&mut buf[..])? == 0 { break; } + } + Ok(Self {}) + } +}