From: Jeffrey Czyz Date: Thu, 18 Jul 2024 16:38:44 +0000 (-0500) Subject: HMAC construction and verification for PaymentID X-Git-Tag: v0.0.124-beta~12^2~18 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=f52bd0b8e3a0750f5a5fd2d2732b483b60c5eac7;p=rust-lightning HMAC construction and verification for PaymentID When receiving an InvoiceError in response to an InvoiceRequest, the corresponding payment should be abandoned. Add functions for constructing and verifying an HMAC over a Payment ID to allow for this. --- diff --git a/lightning/src/offers/signer.rs b/lightning/src/offers/signer.rs index c15b94d49..0aa51cd33 100644 --- a/lightning/src/offers/signer.rs +++ b/lightning/src/offers/signer.rs @@ -36,6 +36,9 @@ const DERIVED_METADATA_AND_KEYS_HMAC_INPUT: &[u8; 16] = &[2; 16]; const WITHOUT_ENCRYPTED_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[3; 16]; const WITH_ENCRYPTED_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[4; 16]; +// HMAC input for a `PaymentId`. The HMAC is used in `OffersContext::OutboundPayment`. +const PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[5; 16]; + /// Message metadata which possibly is derived from [`MetadataMaterial`] such that it can be /// verified. #[derive(Clone)] @@ -391,3 +394,22 @@ fn hmac_for_message<'a>( Ok(hmac) } + +pub(crate) fn hmac_for_payment_id( + payment_id: PaymentId, nonce: Nonce, expanded_key: &ExpandedKey, +) -> Hmac { + const IV_BYTES: &[u8; IV_LEN] = b"LDK Payment ID ~"; + let mut hmac = expanded_key.hmac_for_offer(); + hmac.input(IV_BYTES); + hmac.input(&nonce.0); + hmac.input(PAYMENT_ID_HMAC_INPUT); + hmac.input(&payment_id.0); + + Hmac::from_engine(hmac) +} + +pub(crate) fn verify_payment_id( + payment_id: PaymentId, hmac: Hmac, nonce: Nonce, expanded_key: &ExpandedKey, +) -> bool { + hmac_for_payment_id(payment_id, nonce, expanded_key) == hmac +}