1
1
use bitcoin:: secp256k1;
2
2
3
- use bitcoin:: hashes:: { Hash , HashEngine } ;
3
+ use bitcoin:: hashes:: Hash ;
4
4
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
5
5
use bitcoin:: secp256k1:: { SecretKey , PublicKey } ;
6
6
7
7
use ln:: peers:: { chacha, hkdf5869rfc} ;
8
8
use ln:: peers:: conduit:: { Conduit , SymmetricKey } ;
9
9
use ln:: peers:: handshake:: acts:: { Act , ActBuilder , ACT_ONE_LENGTH , ACT_TWO_LENGTH , ACT_THREE_LENGTH , EMPTY_ACT_ONE , EMPTY_ACT_TWO , EMPTY_ACT_THREE } ;
10
+ use ln:: peers:: handshake:: handshake_hash:: HandshakeHash ;
10
11
11
12
// Alias type to help differentiate between temporary key and chaining key when passing bytes around
12
13
type ChainingKey = [ u8 ; 32 ] ;
13
14
14
- // Generate a SHA-256 hash from one or more elements concatenated together
15
- macro_rules! concat_then_sha256 {
16
- ( $( $x: expr ) ,+ ) => { {
17
- let mut sha = Sha256 :: engine( ) ;
18
- $(
19
- sha. input( $x. as_ref( ) ) ;
20
- ) +
21
- Sha256 :: from_engine( sha)
22
- } }
23
- }
24
-
25
15
pub ( super ) enum HandshakeState {
26
16
InitiatorStarting ( InitiatorStartingState ) ,
27
17
ResponderAwaitingActOne ( ResponderAwaitingActOneState ) ,
@@ -66,17 +56,17 @@ pub(super) struct InitiatorStartingState {
66
56
initiator_ephemeral_private_key : SecretKey ,
67
57
initiator_ephemeral_public_key : PublicKey ,
68
58
responder_static_public_key : PublicKey ,
69
- chaining_key : Sha256 ,
70
- hash : Sha256
59
+ chaining_key : ChainingKey ,
60
+ hash : HandshakeHash ,
71
61
}
72
62
73
63
// Handshake state of the Responder prior to receiving Act 1
74
64
pub ( super ) struct ResponderAwaitingActOneState {
75
65
responder_static_private_key : SecretKey ,
76
66
responder_ephemeral_private_key : SecretKey ,
77
67
responder_ephemeral_public_key : PublicKey ,
78
- chaining_key : Sha256 ,
79
- hash : Sha256 ,
68
+ chaining_key : ChainingKey ,
69
+ hash : HandshakeHash ,
80
70
act_one_builder : ActBuilder
81
71
}
82
72
@@ -87,13 +77,13 @@ pub(super) struct InitiatorAwaitingActTwoState {
87
77
initiator_ephemeral_private_key : SecretKey ,
88
78
responder_static_public_key : PublicKey ,
89
79
chaining_key : ChainingKey ,
90
- hash : Sha256 ,
80
+ hash : HandshakeHash ,
91
81
act_two_builder : ActBuilder
92
82
}
93
83
94
84
// Handshake state of the Responder prior to receiving Act 3
95
85
pub ( super ) struct ResponderAwaitingActThreeState {
96
- hash : Sha256 ,
86
+ hash : HandshakeHash ,
97
87
responder_ephemeral_private_key : SecretKey ,
98
88
chaining_key : ChainingKey ,
99
89
temporary_key : [ u8 ; 32 ] ,
@@ -139,7 +129,7 @@ impl IHandshakeState for InitiatorStartingState {
139
129
& initiator_ephemeral_private_key,
140
130
& initiator_ephemeral_public_key,
141
131
& responder_static_public_key,
142
- chaining_key. into_inner ( ) ,
132
+ chaining_key,
143
133
hash,
144
134
& mut act_one
145
135
) ;
@@ -215,7 +205,7 @@ impl IHandshakeState for ResponderAwaitingActOneState {
215
205
let ( initiator_ephemeral_public_key, hash, chaining_key, _) = process_act_message (
216
206
& act_one,
217
207
& responder_static_private_key,
218
- chaining_key. into_inner ( ) ,
208
+ chaining_key,
219
209
hash,
220
210
) ?;
221
211
@@ -280,7 +270,7 @@ impl IHandshakeState for InitiatorAwaitingActTwoState {
280
270
let chaining_key = self . chaining_key ;
281
271
let act_two = Act :: from ( act_two_builder) ;
282
272
283
- let ( responder_ephemeral_public_key, hash, chaining_key, temporary_key) = process_act_message (
273
+ let ( responder_ephemeral_public_key, mut hash, chaining_key, temporary_key) = process_act_message (
284
274
& act_two,
285
275
& initiator_ephemeral_private_key,
286
276
chaining_key,
@@ -291,10 +281,10 @@ impl IHandshakeState for InitiatorAwaitingActTwoState {
291
281
292
282
// start serializing act three
293
283
// 1. c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed())
294
- chacha:: encrypt ( & temporary_key, 1 , & hash, & initiator_static_public_key. serialize ( ) , & mut act_three[ 1 ..50 ] ) ;
284
+ chacha:: encrypt ( & temporary_key, 1 , & hash. value , & initiator_static_public_key. serialize ( ) , & mut act_three[ 1 ..50 ] ) ;
295
285
296
286
// 2. h = SHA-256(h || c)
297
- let hash = concat_then_sha256 ! ( hash , act_three[ 1 ..50 ] ) ;
287
+ hash. update ( & act_three[ 1 ..50 ] ) ;
298
288
299
289
// 3. se = ECDH(s.priv, re)
300
290
let ecdh = ecdh ( & initiator_static_private_key, & responder_ephemeral_public_key) ;
@@ -303,7 +293,7 @@ impl IHandshakeState for InitiatorAwaitingActTwoState {
303
293
let ( chaining_key, temporary_key) = hkdf5869rfc:: derive ( & chaining_key, & ecdh) ;
304
294
305
295
// 5. t = encryptWithAD(temp_k3, 0, h, zero)
306
- chacha:: encrypt ( & temporary_key, 0 , & hash, & [ 0 ; 0 ] , & mut act_three[ 50 ..] ) ;
296
+ chacha:: encrypt ( & temporary_key, 0 , & hash. value , & [ 0 ; 0 ] , & mut act_three[ 50 ..] ) ;
307
297
308
298
// 6. sk, rk = HKDF(ck, zero)
309
299
let ( sending_key, receiving_key) = hkdf5869rfc:: derive ( & chaining_key, & [ 0 ; 0 ] ) ;
@@ -342,7 +332,7 @@ impl IHandshakeState for ResponderAwaitingActThreeState {
342
332
) ) ;
343
333
}
344
334
345
- let hash = self . hash ;
335
+ let mut hash = self . hash ;
346
336
let temporary_key = self . temporary_key ;
347
337
let responder_ephemeral_private_key = self . responder_ephemeral_private_key ;
348
338
let chaining_key = self . chaining_key ;
@@ -364,15 +354,15 @@ impl IHandshakeState for ResponderAwaitingActThreeState {
364
354
365
355
// 4. rs = decryptWithAD(temp_k2, 1, h, c)
366
356
let mut remote_pubkey = [ 0 ; 33 ] ;
367
- chacha:: decrypt ( & temporary_key, 1 , & hash, & tagged_encrypted_pubkey, & mut remote_pubkey) ?;
357
+ chacha:: decrypt ( & temporary_key, 1 , & hash. value , & tagged_encrypted_pubkey, & mut remote_pubkey) ?;
368
358
let initiator_pubkey = if let Ok ( public_key) = PublicKey :: from_slice ( & remote_pubkey) {
369
359
public_key
370
360
} else {
371
361
return Err ( "invalid remote public key" . to_string ( ) ) ;
372
362
} ;
373
363
374
364
// 5. h = SHA-256(h || c)
375
- let hash = concat_then_sha256 ! ( hash , tagged_encrypted_pubkey) ;
365
+ hash. update ( tagged_encrypted_pubkey) ;
376
366
377
367
// 6. se = ECDH(e.priv, rs)
378
368
let ecdh = ecdh ( & responder_ephemeral_private_key, & initiator_pubkey) ;
@@ -381,7 +371,7 @@ impl IHandshakeState for ResponderAwaitingActThreeState {
381
371
let ( chaining_key, temporary_key) = hkdf5869rfc:: derive ( & chaining_key, & ecdh) ;
382
372
383
373
// 8. p = decryptWithAD(temp_k3, 0, h, t)
384
- chacha:: decrypt ( & temporary_key, 0 , & hash, & chacha_tag, & mut [ 0 ; 0 ] ) ?;
374
+ chacha:: decrypt ( & temporary_key, 0 , & hash. value , & chacha_tag, & mut [ 0 ; 0 ] ) ?;
385
375
386
376
// 9. rk, sk = HKDF(ck, zero)
387
377
let ( receiving_key, sending_key) = hkdf5869rfc:: derive ( & chaining_key, & [ 0 ; 0 ] ) ;
@@ -405,31 +395,32 @@ impl IHandshakeState for ResponderAwaitingActThreeState {
405
395
// the initiator provides the remote's static public key and running on the responder they provide
406
396
// their own.
407
397
// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#handshake-state-initialization
408
- fn initialize_handshake_state ( responder_static_public_key : & PublicKey ) -> ( Sha256 , Sha256 ) {
398
+ fn initialize_handshake_state ( responder_static_public_key : & PublicKey ) -> ( HandshakeHash , [ u8 ; 32 ] ) {
409
399
let protocol_name = b"Noise_XK_secp256k1_ChaChaPoly_SHA256" ;
410
400
let prologue = b"lightning" ;
411
401
412
402
// 1. h = SHA-256(protocolName)
413
403
// 2. ck = h
414
- let chaining_key = concat_then_sha256 ! ( protocol_name) ;
404
+ let mut hash = HandshakeHash :: new ( protocol_name) ;
405
+ let chaining_key = hash. value . clone ( ) ;
415
406
416
407
// 3. h = SHA-256(h || prologue)
417
- let hash = concat_then_sha256 ! ( chaining_key , prologue) ;
408
+ hash. update ( prologue) ;
418
409
419
410
// h = SHA-256(h || responderPublicKey)
420
- let hash = concat_then_sha256 ! ( hash , responder_static_public_key. serialize( ) ) ;
411
+ hash. update ( & responder_static_public_key. serialize ( ) ) ;
421
412
422
413
( hash, chaining_key)
423
414
}
424
415
425
416
// Due to the very high similarity of acts 1 and 2, this method is used to process both
426
417
// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (sender)
427
418
// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (sender)
428
- fn calculate_act_message ( local_private_ephemeral_key : & SecretKey , local_public_ephemeral_key : & PublicKey , remote_public_key : & PublicKey , chaining_key : ChainingKey , hash : Sha256 , act_out : & mut [ u8 ] ) -> ( Sha256 , SymmetricKey , SymmetricKey ) {
419
+ fn calculate_act_message ( local_private_ephemeral_key : & SecretKey , local_public_ephemeral_key : & PublicKey , remote_public_key : & PublicKey , chaining_key : ChainingKey , mut hash : HandshakeHash , act_out : & mut [ u8 ] ) -> ( HandshakeHash , SymmetricKey , SymmetricKey ) {
429
420
// 1. e = generateKey() (passed in)
430
421
// 2. h = SHA-256(h || e.pub.serializeCompressed())
431
422
let serialized_local_public_key = local_public_ephemeral_key. serialize ( ) ;
432
- let hash = concat_then_sha256 ! ( hash , serialized_local_public_key) ;
423
+ hash. update ( & serialized_local_public_key) ;
433
424
434
425
// 3. ACT1: es = ECDH(e.priv, rs)
435
426
// 3. ACT2: es = ECDH(e.priv, re)
@@ -441,10 +432,10 @@ fn calculate_act_message(local_private_ephemeral_key: &SecretKey, local_public_e
441
432
442
433
// 5. ACT1: c = encryptWithAD(temp_k1, 0, h, zero)
443
434
// 5. ACT2: c = encryptWithAD(temp_k2, 0, h, zero)
444
- chacha:: encrypt ( & temporary_key, 0 , & hash, & [ 0 ; 0 ] , & mut act_out[ 34 ..] ) ;
435
+ chacha:: encrypt ( & temporary_key, 0 , & hash. value , & [ 0 ; 0 ] , & mut act_out[ 34 ..] ) ;
445
436
446
437
// 6. h = SHA-256(h || c)
447
- let hash = concat_then_sha256 ! ( hash , & act_out[ 34 ..] ) ;
438
+ hash. update ( & act_out[ 34 ..] ) ;
448
439
449
440
// Send m = 0 || e.pub.serializeCompressed() || c
450
441
act_out[ 0 ] = 0 ;
@@ -456,7 +447,7 @@ fn calculate_act_message(local_private_ephemeral_key: &SecretKey, local_public_e
456
447
// Due to the very high similarity of acts 1 and 2, this method is used to process both
457
448
// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (receiver)
458
449
// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (receiver)
459
- fn process_act_message ( act_bytes : & [ u8 ] , local_private_key : & SecretKey , chaining_key : ChainingKey , hash : Sha256 ) -> Result < ( PublicKey , Sha256 , SymmetricKey , SymmetricKey ) , String > {
450
+ fn process_act_message ( act_bytes : & [ u8 ] , local_private_key : & SecretKey , chaining_key : ChainingKey , mut hash : HandshakeHash ) -> Result < ( PublicKey , HandshakeHash , SymmetricKey , SymmetricKey ) , String > {
460
451
// 1. Read exactly 50 bytes from the network buffer
461
452
// Partial act messages are handled by the callers. By the time it gets here, it
462
453
// must be the correct size.
@@ -481,7 +472,7 @@ fn process_act_message(act_bytes: &[u8], local_private_key: &SecretKey, chaining
481
472
}
482
473
483
474
// 4. h = SHA-256(h || re.serializeCompressed())
484
- let hash = concat_then_sha256 ! ( hash , ephemeral_public_key_bytes) ;
475
+ hash. update ( ephemeral_public_key_bytes) ;
485
476
486
477
// 5. Act1: es = ECDH(s.priv, re)
487
478
// 5. Act2: ee = ECDH(e.priv, ee)
@@ -493,10 +484,10 @@ fn process_act_message(act_bytes: &[u8], local_private_key: &SecretKey, chaining
493
484
494
485
// 7. Act1: p = decryptWithAD(temp_k1, 0, h, c)
495
486
// 7. Act2: p = decryptWithAD(temp_k2, 0, h, c)
496
- chacha:: decrypt ( & temporary_key, 0 , & hash, & chacha_tag, & mut [ 0 ; 0 ] ) ?;
487
+ chacha:: decrypt ( & temporary_key, 0 , & hash. value , & chacha_tag, & mut [ 0 ; 0 ] ) ?;
497
488
498
489
// 8. h = SHA-256(h || c)
499
- let hash = concat_then_sha256 ! ( hash , chacha_tag) ;
490
+ hash. update ( chacha_tag) ;
500
491
501
492
Ok ( ( ephemeral_public_key, hash, chaining_key, temporary_key) )
502
493
}
@@ -513,7 +504,7 @@ fn ecdh(private_key: &SecretKey, public_key: &PublicKey) -> SymmetricKey {
513
504
pk_object. mul_assign ( & curve, & private_key[ ..] ) . expect ( "invalid multiplication" ) ;
514
505
515
506
let preimage = pk_object. serialize ( ) ;
516
- concat_then_sha256 ! ( preimage) . into_inner ( )
507
+ Sha256 :: hash ( & preimage) . into_inner ( )
517
508
}
518
509
519
510
#[ cfg( test) ]
0 commit comments