From: Jeffrey Czyz Date: Tue, 4 Apr 2023 19:59:09 +0000 (-0500) Subject: DRY up verification of invreq TLV records X-Git-Tag: v0.0.115~12^2~3 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=259aa9aac37097c462a25cc39e83ebe2b86ac4bb;p=rust-lightning DRY up verification of invreq TLV records --- diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 57d37a17..17908391 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -108,12 +108,13 @@ use crate::ln::PaymentHash; use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::DecodeError; -use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; +use crate::offers::invoice_request::{INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, IV_BYTES as INVOICE_REQUEST_IV_BYTES, InvoiceRequest, InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TlvStream, WithoutSignatures, self}; -use crate::offers::offer::{Amount, OfferTlvStream, OfferTlvStreamRef}; +use crate::offers::offer::{Amount, OFFER_TYPES, OfferTlvStream, OfferTlvStreamRef}; use crate::offers::parse::{ParseError, ParsedMessage, SemanticError}; -use crate::offers::payer::{PayerTlvStream, PayerTlvStreamRef}; -use crate::offers::refund::{Refund, RefundContents}; +use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef}; +use crate::offers::refund::{IV_BYTES as REFUND_IV_BYTES, Refund, RefundContents}; +use crate::offers::signer; use crate::onion_message::BlindedPath; use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer}; @@ -531,13 +532,32 @@ impl InvoiceContents { fn verify( &self, tlv_stream: TlvStream<'_>, key: &ExpandedKey, secp_ctx: &Secp256k1 ) -> bool { - match self { + let offer_records = tlv_stream.clone().range(OFFER_TYPES); + let invreq_records = tlv_stream.range(INVOICE_REQUEST_TYPES).filter(|record| { + match record.r#type { + PAYER_METADATA_TYPE => false, // Should be outside range + INVOICE_REQUEST_PAYER_ID_TYPE => !self.derives_keys(), + _ => true, + } + }); + let tlv_stream = offer_records.chain(invreq_records); + + let (metadata, payer_id, iv_bytes) = match self { InvoiceContents::ForOffer { invoice_request, .. } => { - invoice_request.verify(tlv_stream, key, secp_ctx) + (invoice_request.metadata(), invoice_request.payer_id(), INVOICE_REQUEST_IV_BYTES) }, InvoiceContents::ForRefund { refund, .. } => { - refund.verify(tlv_stream, key, secp_ctx) + (refund.metadata(), refund.payer_id(), REFUND_IV_BYTES) }, + }; + + signer::verify_metadata(metadata, key, iv_bytes, payer_id, tlv_stream, secp_ctx) + } + + fn derives_keys(&self) -> bool { + match self { + InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.derives_keys(), + InvoiceContents::ForRefund { refund, .. } => refund.derives_keys(), } } diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index 2294fc45..6b5c7786 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -66,10 +66,10 @@ use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce}; use crate::ln::msgs::DecodeError; use crate::offers::invoice::{BlindedPayInfo, InvoiceBuilder}; use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TlvStream, self}; -use crate::offers::offer::{OFFER_TYPES, Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef}; +use crate::offers::offer::{Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef}; use crate::offers::parse::{ParseError, ParsedMessage, SemanticError}; -use crate::offers::payer::{PAYER_METADATA_TYPE, PayerContents, PayerTlvStream, PayerTlvStreamRef}; -use crate::offers::signer::{Metadata, MetadataMaterial, self}; +use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; +use crate::offers::signer::{Metadata, MetadataMaterial}; use crate::onion_message::BlindedPath; use crate::util::ser::{HighZeroBytesDroppedBigSize, SeekReadable, WithoutLength, Writeable, Writer}; use crate::util::string::PrintableString; @@ -78,7 +78,7 @@ use crate::prelude::*; const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice_request", "signature"); -const IV_BYTES: &[u8; IV_LEN] = b"LDK Invreq ~~~~~"; +pub(super) const IV_BYTES: &[u8; IV_LEN] = b"LDK Invreq ~~~~~"; /// Builds an [`InvoiceRequest`] from an [`Offer`] for the "offer to be paid" flow. /// @@ -528,24 +528,16 @@ impl InvoiceRequestContents { self.inner.metadata() } + pub(super) fn derives_keys(&self) -> bool { + self.inner.payer.0.derives_keys() + } + pub(super) fn chain(&self) -> ChainHash { self.inner.chain() } - /// Verifies that the payer metadata was produced from the invoice request in the TLV stream. - pub(super) fn verify( - &self, tlv_stream: TlvStream<'_>, key: &ExpandedKey, secp_ctx: &Secp256k1 - ) -> bool { - let offer_records = tlv_stream.clone().range(OFFER_TYPES); - let invreq_records = tlv_stream.range(INVOICE_REQUEST_TYPES).filter(|record| { - match record.r#type { - PAYER_METADATA_TYPE => false, // Should be outside range - INVOICE_REQUEST_PAYER_ID_TYPE => !self.inner.payer.0.derives_keys(), - _ => true, - } - }); - let tlv_stream = offer_records.chain(invreq_records); - signer::verify_metadata(self.metadata(), key, IV_BYTES, self.payer_id, tlv_stream, secp_ctx) + pub(super) fn payer_id(&self) -> PublicKey { + self.payer_id } pub(super) fn as_tlv_stream(&self) -> PartialInvoiceRequestTlvStreamRef { diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index 8f91db59..582c5b7e 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -85,12 +85,11 @@ use crate::ln::features::InvoiceRequestFeatures; use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; use crate::offers::invoice::{BlindedPayInfo, InvoiceBuilder}; -use crate::offers::invoice_request::{INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; -use crate::offers::merkle::TlvStream; -use crate::offers::offer::{OFFER_TYPES, OfferTlvStream, OfferTlvStreamRef}; +use crate::offers::invoice_request::{InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; +use crate::offers::offer::{OfferTlvStream, OfferTlvStreamRef}; use crate::offers::parse::{Bech32Encode, ParseError, ParsedMessage, SemanticError}; -use crate::offers::payer::{PAYER_METADATA_TYPE, PayerContents, PayerTlvStream, PayerTlvStreamRef}; -use crate::offers::signer::{Metadata, MetadataMaterial, self}; +use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; +use crate::offers::signer::{Metadata, MetadataMaterial}; use crate::onion_message::BlindedPath; use crate::util::ser::{SeekReadable, WithoutLength, Writeable, Writer}; use crate::util::string::PrintableString; @@ -100,7 +99,7 @@ use crate::prelude::*; #[cfg(feature = "std")] use std::time::SystemTime; -const IV_BYTES: &[u8; IV_LEN] = b"LDK Refund ~~~~~"; +pub(super) const IV_BYTES: &[u8; IV_LEN] = b"LDK Refund ~~~~~"; /// Builds a [`Refund`] for the "offer for money" flow. /// @@ -456,7 +455,7 @@ impl RefundContents { } } - fn metadata(&self) -> &[u8] { + pub(super) fn metadata(&self) -> &[u8] { self.payer.0.as_bytes().map(|bytes| bytes.as_slice()).unwrap_or(&[]) } @@ -468,20 +467,12 @@ impl RefundContents { ChainHash::using_genesis_block(Network::Bitcoin) } - /// Verifies that the payer metadata was produced from the refund in the TLV stream. - pub(super) fn verify( - &self, tlv_stream: TlvStream<'_>, key: &ExpandedKey, secp_ctx: &Secp256k1 - ) -> bool { - let offer_records = tlv_stream.clone().range(OFFER_TYPES); - let invreq_records = tlv_stream.range(INVOICE_REQUEST_TYPES).filter(|record| { - match record.r#type { - PAYER_METADATA_TYPE => false, // Should be outside range - INVOICE_REQUEST_PAYER_ID_TYPE => !self.payer.0.derives_keys(), - _ => true, - } - }); - let tlv_stream = offer_records.chain(invreq_records); - signer::verify_metadata(self.metadata(), key, IV_BYTES, self.payer_id, tlv_stream, secp_ctx) + pub(super) fn derives_keys(&self) -> bool { + self.payer.0.derives_keys() + } + + pub(super) fn payer_id(&self) -> PublicKey { + self.payer_id } pub(super) fn as_tlv_stream(&self) -> RefundTlvStreamRef {