@@ -73,12 +73,14 @@ use core::ops::Deref;
7373use std:: time:: Instant ;
7474
7575mod inbound_payment {
76+ use alloc:: string:: ToString ;
7677 use bitcoin:: hashes:: { Hash , HashEngine } ;
7778 use bitcoin:: hashes:: cmp:: fixed_time_eq;
7879 use bitcoin:: hashes:: hmac:: { Hmac , HmacEngine } ;
7980 use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
8081 use chain:: keysinterface:: { KeyMaterial , KeysInterface , Sign } ;
8182 use ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
83+ use ln:: channelmanager:: APIError ;
8284 use ln:: msgs;
8385 use ln:: msgs:: MAX_VALUE_MSAT ;
8486 use util:: chacha20:: ChaCha20 ;
@@ -113,7 +115,7 @@ mod inbound_payment {
113115
114116 impl ExpandedKey {
115117 pub ( super ) fn new ( key_material : & KeyMaterial ) -> ExpandedKey {
116- hkdf_extract_expand ( & vec ! [ 0 ] , & key_material)
118+ hkdf_extract_expand ( b"LDK Inbound Payment Key Expansion" , & key_material)
117119 }
118120 }
119121
@@ -237,15 +239,7 @@ mod inbound_payment {
237239 pub ( super ) fn verify < L : Deref > ( payment_hash : PaymentHash , payment_data : msgs:: FinalOnionHopData , highest_seen_timestamp : u64 , keys : & ExpandedKey , logger : & L ) -> Result < Option < PaymentPreimage > , ( ) >
238240 where L :: Target : Logger
239241 {
240- let mut iv_bytes = [ 0 ; IV_LEN ] ;
241- let ( iv_slice, encrypted_metadata_bytes) = payment_data. payment_secret . 0 . split_at ( IV_LEN ) ;
242- iv_bytes. copy_from_slice ( iv_slice) ;
243-
244- let chacha_block = ChaCha20 :: get_single_block ( & keys. metadata_key , & iv_bytes) ;
245- let mut metadata_bytes: [ u8 ; METADATA_LEN ] = [ 0 ; METADATA_LEN ] ;
246- for i in 0 ..METADATA_LEN {
247- metadata_bytes[ i] = chacha_block[ i] ^ encrypted_metadata_bytes[ i] ;
248- }
242+ let ( iv_bytes, metadata_bytes) = decrypt_metadata ( payment_data. payment_secret , keys) ;
249243
250244 let payment_type_res = Method :: from_bits ( ( metadata_bytes[ 0 ] & 0b1110_0000 ) >> METHOD_TYPE_OFFSET ) ;
251245 let mut amt_msat_bytes = [ 0 ; AMT_MSAT_LEN ] ;
@@ -269,15 +263,13 @@ mod inbound_payment {
269263 }
270264 } ,
271265 Ok ( Method :: LdkPaymentHash ) => {
272- let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. ldk_pmt_hash_key ) ;
273- hmac. input ( & iv_bytes) ;
274- hmac. input ( & metadata_bytes) ;
275- let decoded_payment_preimage = Hmac :: from_engine ( hmac) . into_inner ( ) ;
276- if !fixed_time_eq ( & payment_hash. 0 , & Sha256 :: hash ( & decoded_payment_preimage) . into_inner ( ) ) {
277- log_trace ! ( logger, "Failing HTLC with payment_hash {}: payment preimage {} did not match" , log_bytes!( payment_hash. 0 ) , log_bytes!( decoded_payment_preimage) ) ;
278- return Err ( ( ) )
266+ match derive_ldk_payment_preimage ( payment_hash, & iv_bytes, & metadata_bytes, keys) {
267+ Ok ( preimage) => payment_preimage = Some ( preimage) ,
268+ Err ( bad_preimage_bytes) => {
269+ log_trace ! ( logger, "Failing HTLC with payment_hash {} due to mismatching preimage {}" , log_bytes!( payment_hash. 0 ) , log_bytes!( bad_preimage_bytes) ) ;
270+ return Err ( ( ) )
271+ }
279272 }
280- payment_preimage = Some ( PaymentPreimage ( decoded_payment_preimage) ) ;
281273 } ,
282274 Err ( unknown_bits) => {
283275 log_trace ! ( logger, "Failing HTLC with payment hash {} due to unknown payment type {}" , log_bytes!( payment_hash. 0 ) , unknown_bits) ;
@@ -298,6 +290,50 @@ mod inbound_payment {
298290 Ok ( payment_preimage)
299291 }
300292
293+ pub ( super ) fn get_payment_preimage ( payment_hash : PaymentHash , payment_secret : PaymentSecret , keys : & ExpandedKey ) -> Result < PaymentPreimage , APIError > {
294+ let ( iv_bytes, metadata_bytes) = decrypt_metadata ( payment_secret, keys) ;
295+
296+ match Method :: from_bits ( ( metadata_bytes[ 0 ] & 0b1110_0000 ) >> METHOD_TYPE_OFFSET ) {
297+ Ok ( Method :: LdkPaymentHash ) => {
298+ derive_ldk_payment_preimage ( payment_hash, & iv_bytes, & metadata_bytes, keys)
299+ . map_err ( |bad_preimage_bytes| APIError :: APIMisuseError {
300+ err : format ! ( "Payment hash {} did not match decoded preimage {}" , log_bytes!( payment_hash. 0 ) , log_bytes!( bad_preimage_bytes) )
301+ } )
302+ } ,
303+ Ok ( Method :: UserPaymentHash ) => Err ( APIError :: APIMisuseError {
304+ err : "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash" . to_string ( )
305+ } ) ,
306+ Err ( other) => Err ( APIError :: APIMisuseError { err : format ! ( "Unknown payment type: {}" , other) } ) ,
307+ }
308+ }
309+
310+ fn decrypt_metadata ( payment_secret : PaymentSecret , keys : & ExpandedKey ) -> ( [ u8 ; IV_LEN ] , [ u8 ; METADATA_LEN ] ) {
311+ let mut iv_bytes = [ 0 ; IV_LEN ] ;
312+ let ( iv_slice, encrypted_metadata_bytes) = payment_secret. 0 . split_at ( IV_LEN ) ;
313+ iv_bytes. copy_from_slice ( iv_slice) ;
314+
315+ let chacha_block = ChaCha20 :: get_single_block ( & keys. metadata_key , & iv_bytes) ;
316+ let mut metadata_bytes: [ u8 ; METADATA_LEN ] = [ 0 ; METADATA_LEN ] ;
317+ for i in 0 ..METADATA_LEN {
318+ metadata_bytes[ i] = chacha_block[ i] ^ encrypted_metadata_bytes[ i] ;
319+ }
320+
321+ ( iv_bytes, metadata_bytes)
322+ }
323+
324+ // Errors if the payment preimage doesn't match `payment_hash`. Returns the bad preimage bytes in
325+ // this case.
326+ fn derive_ldk_payment_preimage ( payment_hash : PaymentHash , iv_bytes : & [ u8 ; IV_LEN ] , metadata_bytes : & [ u8 ; METADATA_LEN ] , keys : & ExpandedKey ) -> Result < PaymentPreimage , [ u8 ; 32 ] > {
327+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. ldk_pmt_hash_key ) ;
328+ hmac. input ( iv_bytes) ;
329+ hmac. input ( metadata_bytes) ;
330+ let decoded_payment_preimage = Hmac :: from_engine ( hmac) . into_inner ( ) ;
331+ if !fixed_time_eq ( & payment_hash. 0 , & Sha256 :: hash ( & decoded_payment_preimage) . into_inner ( ) ) {
332+ return Err ( decoded_payment_preimage) ;
333+ }
334+ return Ok ( PaymentPreimage ( decoded_payment_preimage) )
335+ }
336+
301337 fn hkdf_extract_expand ( salt : & [ u8 ] , ikm : & KeyMaterial ) -> ExpandedKey {
302338 let mut hmac = HmacEngine :: < Sha256 > :: new ( salt) ;
303339 hmac. input ( & ikm. 0 ) ;
@@ -5026,8 +5062,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
50265062 /// payment secret fetched via this method or [`create_inbound_payment`], and which is at least
50275063 /// the `min_value_msat` provided here, if one is provided.
50285064 ///
5029- /// The [`PaymentHash`] (and corresponding [`PaymentPreimage`]) must be globally unique. This
5030- /// method may return an Err if another payment with the same payment_hash is still pending.
5065+ /// The [`PaymentHash`] (and corresponding [`PaymentPreimage`]) should be globally unique, though
5066+ /// note that LDK will not stop you from registering duplicate payment hashes for inbound
5067+ /// payments.
50315068 ///
50325069 /// `min_value_msat` should be set if the invoice being generated contains a value. Any payment
50335070 /// received for the returned [`PaymentHash`] will be required to be at least `min_value_msat`
@@ -5079,6 +5116,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
50795116 self . set_payment_hash_secret_map ( payment_hash, None , min_value_msat, invoice_expiry_delta_secs)
50805117 }
50815118
5119+ /// Gets an LDK-generated payment preimage from a payment hash and payment secret that were
5120+ /// previously returned from [`create_inbound_payment`].
5121+ ///
5122+ /// [`create_inbound_payment`]: Self::create_inbound_payment
5123+ pub fn get_payment_preimage ( & self , payment_hash : PaymentHash , payment_secret : PaymentSecret ) -> Result < PaymentPreimage , APIError > {
5124+ inbound_payment:: get_payment_preimage ( payment_hash, payment_secret, & self . inbound_payment_key )
5125+ }
5126+
50825127 #[ cfg( any( test, feature = "fuzztarget" , feature = "_test_utils" ) ) ]
50835128 pub fn get_and_clear_pending_events ( & self ) -> Vec < events:: Event > {
50845129 let events = core:: cell:: RefCell :: new ( Vec :: new ( ) ) ;
0 commit comments