]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Add PaymentId authentication to public API
authorJeffrey Czyz <jkczyz@gmail.com>
Wed, 14 Aug 2024 22:39:13 +0000 (17:39 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Fri, 16 Aug 2024 20:43:43 +0000 (15:43 -0500)
When receiving an InvoiceError message, it should be authenticated
before using it to abandon the payment. Add methods to PaymentId's
public API for constructing and verifying an HMAC for use in
OffersContext::OutboundPayment. This allows other implementations of
OffersMessageHandler to construct the HMAC and authenticate the message.

lightning/src/ln/channelmanager.rs

index 303c0d59ea2307e954c5318b374ed4a37d95686f..316148b1c5ea667721a4e4c605842838138b4881 100644 (file)
@@ -24,6 +24,7 @@ use bitcoin::key::constants::SECRET_KEY_SIZE;
 use bitcoin::network::Network;
 
 use bitcoin::hashes::Hash;
+use bitcoin::hashes::hmac::Hmac;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hash_types::{BlockHash, Txid};
 
@@ -413,6 +414,22 @@ pub struct PaymentId(pub [u8; Self::LENGTH]);
 impl PaymentId {
        /// Number of bytes in the id.
        pub const LENGTH: usize = 32;
+
+       /// Constructs an HMAC to include in [`OffersContext::OutboundPayment`] for the payment id
+       /// along with the given [`Nonce`].
+       pub fn hmac_for_offer_payment(
+               &self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey,
+       ) -> Hmac<Sha256> {
+               signer::hmac_for_payment_id(*self, nonce, expanded_key)
+       }
+
+       /// Authenticates the payment id using an HMAC and a [`Nonce`] taken from an
+       /// [`OffersContext::OutboundPayment`].
+       pub fn verify(
+               &self, hmac: Hmac<Sha256>, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey,
+       ) -> Result<(), ()> {
+               signer::verify_payment_id(*self, hmac, nonce, expanded_key)
+       }
 }
 
 impl Writeable for PaymentId {
@@ -9024,7 +9041,7 @@ where
                };
                let invoice_request = builder.build_and_sign()?;
 
-               let hmac = signer::hmac_for_payment_id(payment_id, nonce, expanded_key);
+               let hmac = payment_id.hmac_for_offer_payment(nonce, expanded_key);
                let context = OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) };
                let reply_paths = self.create_blinded_paths(context)
                        .map_err(|_| Bolt12SemanticError::MissingPaths)?;
@@ -10900,7 +10917,7 @@ where
 
                                match context {
                                        Some(OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) }) => {
-                                               if let Ok(()) = signer::verify_payment_id(payment_id, hmac, nonce, expanded_key) {
+                                               if let Ok(()) = payment_id.verify(hmac, nonce, expanded_key) {
                                                        self.abandon_payment_with_reason(
                                                                payment_id, PaymentFailureReason::InvoiceRequestRejected,
                                                        );