@@ -40,7 +40,7 @@ use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitor
40
40
use chain:: transaction:: { OutPoint , TransactionData } ;
41
41
// Since this struct is returned in `list_channels` methods, expose it here in case users want to
42
42
// construct one themselves.
43
- use ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
43
+ use ln:: { inbound_payment , PaymentHash , PaymentPreimage , PaymentSecret } ;
44
44
use ln:: channel:: { Channel , ChannelError , ChannelUpdateStatus , UpdateFulfillCommitFetch } ;
45
45
use ln:: features:: { InitFeatures , NodeFeatures } ;
46
46
use routing:: router:: { PaymentParameters , Route , RouteHop , RoutePath , RouteParameters } ;
@@ -70,276 +70,6 @@ use core::ops::Deref;
70
70
#[ cfg( any( test, feature = "std" ) ) ]
71
71
use std:: time:: Instant ;
72
72
73
- mod inbound_payment {
74
- use alloc:: string:: ToString ;
75
- use bitcoin:: hashes:: { Hash , HashEngine } ;
76
- use bitcoin:: hashes:: cmp:: fixed_time_eq;
77
- use bitcoin:: hashes:: hmac:: { Hmac , HmacEngine } ;
78
- use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
79
- use chain:: keysinterface:: { KeyMaterial , KeysInterface , Sign } ;
80
- use ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
81
- use ln:: channelmanager:: APIError ;
82
- use ln:: msgs;
83
- use ln:: msgs:: MAX_VALUE_MSAT ;
84
- use util:: chacha20:: ChaCha20 ;
85
- use util:: crypto:: hkdf_extract_expand_thrice;
86
- use util:: logger:: Logger ;
87
-
88
- use core:: convert:: TryInto ;
89
- use core:: ops:: Deref ;
90
-
91
- const IV_LEN : usize = 16 ;
92
- const METADATA_LEN : usize = 16 ;
93
- const METADATA_KEY_LEN : usize = 32 ;
94
- const AMT_MSAT_LEN : usize = 8 ;
95
- // Used to shift the payment type bits to take up the top 3 bits of the metadata bytes, or to
96
- // retrieve said payment type bits.
97
- const METHOD_TYPE_OFFSET : usize = 5 ;
98
-
99
- /// A set of keys that were HKDF-expanded from an initial call to
100
- /// [`KeysInterface::get_inbound_payment_key_material`].
101
- ///
102
- /// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
103
- pub ( super ) struct ExpandedKey {
104
- /// The key used to encrypt the bytes containing the payment metadata (i.e. the amount and
105
- /// expiry, included for payment verification on decryption).
106
- metadata_key : [ u8 ; 32 ] ,
107
- /// The key used to authenticate an LDK-provided payment hash and metadata as previously
108
- /// registered with LDK.
109
- ldk_pmt_hash_key : [ u8 ; 32 ] ,
110
- /// The key used to authenticate a user-provided payment hash and metadata as previously
111
- /// registered with LDK.
112
- user_pmt_hash_key : [ u8 ; 32 ] ,
113
- }
114
-
115
- impl ExpandedKey {
116
- pub ( super ) fn new ( key_material : & KeyMaterial ) -> ExpandedKey {
117
- let ( metadata_key, ldk_pmt_hash_key, user_pmt_hash_key) =
118
- hkdf_extract_expand_thrice ( b"LDK Inbound Payment Key Expansion" , & key_material. 0 ) ;
119
- Self {
120
- metadata_key,
121
- ldk_pmt_hash_key,
122
- user_pmt_hash_key,
123
- }
124
- }
125
- }
126
-
127
- enum Method {
128
- LdkPaymentHash = 0 ,
129
- UserPaymentHash = 1 ,
130
- }
131
-
132
- impl Method {
133
- fn from_bits ( bits : u8 ) -> Result < Method , u8 > {
134
- match bits {
135
- bits if bits == Method :: LdkPaymentHash as u8 => Ok ( Method :: LdkPaymentHash ) ,
136
- bits if bits == Method :: UserPaymentHash as u8 => Ok ( Method :: UserPaymentHash ) ,
137
- unknown => Err ( unknown) ,
138
- }
139
- }
140
- }
141
-
142
- pub ( super ) fn create < Signer : Sign , K : Deref > ( keys : & ExpandedKey , min_value_msat : Option < u64 > , invoice_expiry_delta_secs : u32 , keys_manager : & K , highest_seen_timestamp : u64 ) -> Result < ( PaymentHash , PaymentSecret ) , ( ) >
143
- where K :: Target : KeysInterface < Signer = Signer >
144
- {
145
- let metadata_bytes = construct_metadata_bytes ( min_value_msat, Method :: LdkPaymentHash , invoice_expiry_delta_secs, highest_seen_timestamp) ?;
146
-
147
- let mut iv_bytes = [ 0 as u8 ; IV_LEN ] ;
148
- let rand_bytes = keys_manager. get_secure_random_bytes ( ) ;
149
- iv_bytes. copy_from_slice ( & rand_bytes[ ..IV_LEN ] ) ;
150
-
151
- let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. ldk_pmt_hash_key ) ;
152
- hmac. input ( & iv_bytes) ;
153
- hmac. input ( & metadata_bytes) ;
154
- let payment_preimage_bytes = Hmac :: from_engine ( hmac) . into_inner ( ) ;
155
-
156
- let ldk_pmt_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage_bytes) . into_inner ( ) ) ;
157
- let payment_secret = construct_payment_secret ( & iv_bytes, & metadata_bytes, & keys. metadata_key ) ;
158
- Ok ( ( ldk_pmt_hash, payment_secret) )
159
- }
160
-
161
- pub ( super ) fn create_from_hash ( keys : & ExpandedKey , min_value_msat : Option < u64 > , payment_hash : PaymentHash , invoice_expiry_delta_secs : u32 , highest_seen_timestamp : u64 ) -> Result < PaymentSecret , ( ) > {
162
- let metadata_bytes = construct_metadata_bytes ( min_value_msat, Method :: UserPaymentHash , invoice_expiry_delta_secs, highest_seen_timestamp) ?;
163
-
164
- let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. user_pmt_hash_key ) ;
165
- hmac. input ( & metadata_bytes) ;
166
- hmac. input ( & payment_hash. 0 ) ;
167
- let hmac_bytes = Hmac :: from_engine ( hmac) . into_inner ( ) ;
168
-
169
- let mut iv_bytes = [ 0 as u8 ; IV_LEN ] ;
170
- iv_bytes. copy_from_slice ( & hmac_bytes[ ..IV_LEN ] ) ;
171
-
172
- Ok ( construct_payment_secret ( & iv_bytes, & metadata_bytes, & keys. metadata_key ) )
173
- }
174
-
175
- fn construct_metadata_bytes ( min_value_msat : Option < u64 > , payment_type : Method , invoice_expiry_delta_secs : u32 , highest_seen_timestamp : u64 ) -> Result < [ u8 ; METADATA_LEN ] , ( ) > {
176
- if min_value_msat. is_some ( ) && min_value_msat. unwrap ( ) > MAX_VALUE_MSAT {
177
- return Err ( ( ) ) ;
178
- }
179
-
180
- let mut min_amt_msat_bytes: [ u8 ; AMT_MSAT_LEN ] = match min_value_msat {
181
- Some ( amt) => amt. to_be_bytes ( ) ,
182
- None => [ 0 ; AMT_MSAT_LEN ] ,
183
- } ;
184
- min_amt_msat_bytes[ 0 ] |= ( payment_type as u8 ) << METHOD_TYPE_OFFSET ;
185
-
186
- // We assume that highest_seen_timestamp is pretty close to the current time - it's updated when
187
- // we receive a new block with the maximum time we've seen in a header. It should never be more
188
- // than two hours in the future. Thus, we add two hours here as a buffer to ensure we
189
- // absolutely never fail a payment too early.
190
- // Note that we assume that received blocks have reasonably up-to-date timestamps.
191
- let expiry_bytes = ( highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200 ) . to_be_bytes ( ) ;
192
-
193
- let mut metadata_bytes: [ u8 ; METADATA_LEN ] = [ 0 ; METADATA_LEN ] ;
194
- metadata_bytes[ ..AMT_MSAT_LEN ] . copy_from_slice ( & min_amt_msat_bytes) ;
195
- metadata_bytes[ AMT_MSAT_LEN ..] . copy_from_slice ( & expiry_bytes) ;
196
-
197
- Ok ( metadata_bytes)
198
- }
199
-
200
- fn construct_payment_secret ( iv_bytes : & [ u8 ; IV_LEN ] , metadata_bytes : & [ u8 ; METADATA_LEN ] , metadata_key : & [ u8 ; METADATA_KEY_LEN ] ) -> PaymentSecret {
201
- let mut payment_secret_bytes: [ u8 ; 32 ] = [ 0 ; 32 ] ;
202
- let ( iv_slice, encrypted_metadata_slice) = payment_secret_bytes. split_at_mut ( IV_LEN ) ;
203
- iv_slice. copy_from_slice ( iv_bytes) ;
204
-
205
- let chacha_block = ChaCha20 :: get_single_block ( metadata_key, iv_bytes) ;
206
- for i in 0 ..METADATA_LEN {
207
- encrypted_metadata_slice[ i] = chacha_block[ i] ^ metadata_bytes[ i] ;
208
- }
209
- PaymentSecret ( payment_secret_bytes)
210
- }
211
-
212
- /// Check that an inbound payment's `payment_data` field is sane.
213
- ///
214
- /// LDK does not store any data for pending inbound payments. Instead, we construct our payment
215
- /// secret (and, if supplied by LDK, our payment preimage) to include encrypted metadata about the
216
- /// payment.
217
- ///
218
- /// The metadata is constructed as:
219
- /// payment method (3 bits) || payment amount (8 bytes - 3 bits) || expiry (8 bytes)
220
- /// and encrypted using a key derived from [`KeysInterface::get_inbound_payment_key_material`].
221
- ///
222
- /// Then on payment receipt, we verify in this method that the payment preimage and payment secret
223
- /// match what was constructed.
224
- ///
225
- /// [`create_inbound_payment`] and [`create_inbound_payment_for_hash`] are called by the user to
226
- /// construct the payment secret and/or payment hash that this method is verifying. If the former
227
- /// method is called, then the payment method bits mentioned above are represented internally as
228
- /// [`Method::LdkPaymentHash`]. If the latter, [`Method::UserPaymentHash`].
229
- ///
230
- /// For the former method, the payment preimage is constructed as an HMAC of payment metadata and
231
- /// random bytes. Because the payment secret is also encoded with these random bytes and metadata
232
- /// (with the metadata encrypted with a block cipher), we're able to authenticate the preimage on
233
- /// payment receipt.
234
- ///
235
- /// For the latter, the payment secret instead contains an HMAC of the user-provided payment hash
236
- /// and payment metadata (encrypted with a block cipher), allowing us to authenticate the payment
237
- /// hash and metadata on payment receipt.
238
- ///
239
- /// See [`ExpandedKey`] docs for more info on the individual keys used.
240
- ///
241
- /// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
242
- /// [`create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
243
- /// [`create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
244
- pub ( super ) fn verify < L : Deref > ( payment_hash : PaymentHash , payment_data : msgs:: FinalOnionHopData , highest_seen_timestamp : u64 , keys : & ExpandedKey , logger : & L ) -> Result < Option < PaymentPreimage > , ( ) >
245
- where L :: Target : Logger
246
- {
247
- let ( iv_bytes, metadata_bytes) = decrypt_metadata ( payment_data. payment_secret , keys) ;
248
-
249
- let payment_type_res = Method :: from_bits ( ( metadata_bytes[ 0 ] & 0b1110_0000 ) >> METHOD_TYPE_OFFSET ) ;
250
- let mut amt_msat_bytes = [ 0 ; AMT_MSAT_LEN ] ;
251
- amt_msat_bytes. copy_from_slice ( & metadata_bytes[ ..AMT_MSAT_LEN ] ) ;
252
- // Zero out the bits reserved to indicate the payment type.
253
- amt_msat_bytes[ 0 ] &= 0b00011111 ;
254
- let min_amt_msat: u64 = u64:: from_be_bytes ( amt_msat_bytes. into ( ) ) ;
255
- let expiry = u64:: from_be_bytes ( metadata_bytes[ AMT_MSAT_LEN ..] . try_into ( ) . unwrap ( ) ) ;
256
-
257
- // Make sure to check to check the HMAC before doing the other checks below, to mitigate timing
258
- // attacks.
259
- let mut payment_preimage = None ;
260
- match payment_type_res {
261
- Ok ( Method :: UserPaymentHash ) => {
262
- let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. user_pmt_hash_key ) ;
263
- hmac. input ( & metadata_bytes[ ..] ) ;
264
- hmac. input ( & payment_hash. 0 ) ;
265
- if !fixed_time_eq ( & iv_bytes, & Hmac :: from_engine ( hmac) . into_inner ( ) . split_at_mut ( IV_LEN ) . 0 ) {
266
- log_trace ! ( logger, "Failing HTLC with user-generated payment_hash {}: unexpected payment_secret" , log_bytes!( payment_hash. 0 ) ) ;
267
- return Err ( ( ) )
268
- }
269
- } ,
270
- Ok ( Method :: LdkPaymentHash ) => {
271
- match derive_ldk_payment_preimage ( payment_hash, & iv_bytes, & metadata_bytes, keys) {
272
- Ok ( preimage) => payment_preimage = Some ( preimage) ,
273
- Err ( bad_preimage_bytes) => {
274
- log_trace ! ( logger, "Failing HTLC with payment_hash {} due to mismatching preimage {}" , log_bytes!( payment_hash. 0 ) , log_bytes!( bad_preimage_bytes) ) ;
275
- return Err ( ( ) )
276
- }
277
- }
278
- } ,
279
- Err ( unknown_bits) => {
280
- log_trace ! ( logger, "Failing HTLC with payment hash {} due to unknown payment type {}" , log_bytes!( payment_hash. 0 ) , unknown_bits) ;
281
- return Err ( ( ) ) ;
282
- }
283
- }
284
-
285
- if payment_data. total_msat < min_amt_msat {
286
- log_trace ! ( logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat" , log_bytes!( payment_hash. 0 ) , payment_data. total_msat, min_amt_msat) ;
287
- return Err ( ( ) )
288
- }
289
-
290
- if expiry < highest_seen_timestamp {
291
- log_trace ! ( logger, "Failing HTLC with payment_hash {}: expired payment" , log_bytes!( payment_hash. 0 ) ) ;
292
- return Err ( ( ) )
293
- }
294
-
295
- Ok ( payment_preimage)
296
- }
297
-
298
- pub ( super ) fn get_payment_preimage ( payment_hash : PaymentHash , payment_secret : PaymentSecret , keys : & ExpandedKey ) -> Result < PaymentPreimage , APIError > {
299
- let ( iv_bytes, metadata_bytes) = decrypt_metadata ( payment_secret, keys) ;
300
-
301
- match Method :: from_bits ( ( metadata_bytes[ 0 ] & 0b1110_0000 ) >> METHOD_TYPE_OFFSET ) {
302
- Ok ( Method :: LdkPaymentHash ) => {
303
- derive_ldk_payment_preimage ( payment_hash, & iv_bytes, & metadata_bytes, keys)
304
- . map_err ( |bad_preimage_bytes| APIError :: APIMisuseError {
305
- err : format ! ( "Payment hash {} did not match decoded preimage {}" , log_bytes!( payment_hash. 0 ) , log_bytes!( bad_preimage_bytes) )
306
- } )
307
- } ,
308
- Ok ( Method :: UserPaymentHash ) => Err ( APIError :: APIMisuseError {
309
- err : "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash" . to_string ( )
310
- } ) ,
311
- Err ( other) => Err ( APIError :: APIMisuseError { err : format ! ( "Unknown payment type: {}" , other) } ) ,
312
- }
313
- }
314
-
315
- fn decrypt_metadata ( payment_secret : PaymentSecret , keys : & ExpandedKey ) -> ( [ u8 ; IV_LEN ] , [ u8 ; METADATA_LEN ] ) {
316
- let mut iv_bytes = [ 0 ; IV_LEN ] ;
317
- let ( iv_slice, encrypted_metadata_bytes) = payment_secret. 0 . split_at ( IV_LEN ) ;
318
- iv_bytes. copy_from_slice ( iv_slice) ;
319
-
320
- let chacha_block = ChaCha20 :: get_single_block ( & keys. metadata_key , & iv_bytes) ;
321
- let mut metadata_bytes: [ u8 ; METADATA_LEN ] = [ 0 ; METADATA_LEN ] ;
322
- for i in 0 ..METADATA_LEN {
323
- metadata_bytes[ i] = chacha_block[ i] ^ encrypted_metadata_bytes[ i] ;
324
- }
325
-
326
- ( iv_bytes, metadata_bytes)
327
- }
328
-
329
- // Errors if the payment preimage doesn't match `payment_hash`. Returns the bad preimage bytes in
330
- // this case.
331
- fn derive_ldk_payment_preimage ( payment_hash : PaymentHash , iv_bytes : & [ u8 ; IV_LEN ] , metadata_bytes : & [ u8 ; METADATA_LEN ] , keys : & ExpandedKey ) -> Result < PaymentPreimage , [ u8 ; 32 ] > {
332
- let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. ldk_pmt_hash_key ) ;
333
- hmac. input ( iv_bytes) ;
334
- hmac. input ( metadata_bytes) ;
335
- let decoded_payment_preimage = Hmac :: from_engine ( hmac) . into_inner ( ) ;
336
- if !fixed_time_eq ( & payment_hash. 0 , & Sha256 :: hash ( & decoded_payment_preimage) . into_inner ( ) ) {
337
- return Err ( decoded_payment_preimage) ;
338
- }
339
- return Ok ( PaymentPreimage ( decoded_payment_preimage) )
340
- }
341
- }
342
-
343
73
// We hold various information about HTLC relay in the HTLC objects in Channel itself:
344
74
//
345
75
// Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should
@@ -7481,7 +7211,7 @@ mod tests {
7481
7211
match inbound_payment:: verify ( bad_payment_hash, payment_data. clone ( ) , nodes[ 0 ] . node . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64 , & nodes[ 0 ] . node . inbound_payment_key , & nodes[ 0 ] . logger ) {
7482
7212
Ok ( _) => panic ! ( "Unexpected ok" ) ,
7483
7213
Err ( ( ) ) => {
7484
- nodes[ 0 ] . logger . assert_log_contains ( "lightning::ln::channelmanager:: inbound_payment" . to_string ( ) , "Failing HTLC with user-generated payment_hash" . to_string ( ) , 1 ) ;
7214
+ nodes[ 0 ] . logger . assert_log_contains ( "lightning::ln::inbound_payment" . to_string ( ) , "Failing HTLC with user-generated payment_hash" . to_string ( ) , 1 ) ;
7485
7215
}
7486
7216
}
7487
7217
0 commit comments