Skip to content

Commit 4fb5708

Browse files
authored
Merge pull request #2411 from valentinewallace/2023-07-blinded-onion-keys
Support constructing blinded path onion keys
2 parents 8f02430 + 7b31712 commit 4fb5708

File tree

6 files changed

+352
-248
lines changed

6 files changed

+352
-248
lines changed

lightning/src/blinded_path/mod.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111
1212
pub(crate) mod utils;
1313

14-
use bitcoin::hashes::{Hash, HashEngine};
15-
use bitcoin::hashes::sha256::Hash as Sha256;
16-
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
14+
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
1715

1816
use crate::sign::{EntropySource, NodeSigner, Recipient};
1917
use crate::onion_message::ControlTlvs;
@@ -97,14 +95,8 @@ impl BlindedPath {
9795
let mut new_blinding_point = match next_blinding_override {
9896
Some(blinding_point) => blinding_point,
9997
None => {
100-
let blinding_factor = {
101-
let mut sha = Sha256::engine();
102-
sha.input(&self.blinding_point.serialize()[..]);
103-
sha.input(control_tlvs_ss.as_ref());
104-
Sha256::from_engine(sha).into_inner()
105-
};
106-
self.blinding_point.mul_tweak(secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap())
107-
.map_err(|_| ())?
98+
onion_utils::next_hop_pubkey(secp_ctx, self.blinding_point,
99+
control_tlvs_ss.as_ref()).map_err(|_| ())?
108100
}
109101
};
110102
mem::swap(&mut self.blinding_point, &mut new_blinding_point);

lightning/src/ln/channelmanager.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2914,9 +2914,9 @@ where
29142914
short_channel_id, amt_to_forward, outgoing_cltv_value
29152915
}, ..
29162916
} => {
2917-
let next_pk = onion_utils::next_hop_packet_pubkey(&self.secp_ctx,
2917+
let next_packet_pk = onion_utils::next_hop_pubkey(&self.secp_ctx,
29182918
msg.onion_routing_packet.public_key.unwrap(), &shared_secret);
2919-
(short_channel_id, amt_to_forward, outgoing_cltv_value, Some(next_pk))
2919+
(short_channel_id, amt_to_forward, outgoing_cltv_value, Some(next_packet_pk))
29202920
},
29212921
// We'll do receive checks in [`Self::construct_pending_htlc_info`] so we have access to the
29222922
// inbound channel's state.

lightning/src/ln/onion_route_tests.rs

+51-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ use crate::util::errors::APIError;
3131

3232
use bitcoin::hash_types::BlockHash;
3333

34-
use bitcoin::hashes::Hash;
34+
use bitcoin::hashes::{Hash, HashEngine};
35+
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
3536
use bitcoin::hashes::sha256::Hash as Sha256;
3637

3738
use bitcoin::secp256k1;
@@ -57,7 +58,12 @@ fn run_onion_failure_test<F1,F2>(_name: &str, test_case: u8, nodes: &Vec<Node>,
5758
// 3: final node fails backward (but tamper onion payloads from node0)
5859
// 100: trigger error in the intermediate node and tamper returning fail_htlc
5960
// 200: trigger error in the final node and tamper returning fail_htlc
60-
fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash, payment_secret: &PaymentSecret, mut callback_msg: F1, mut callback_fail: F2, mut callback_node: F3, expected_retryable: bool, expected_error_code: Option<u16>, expected_channel_update: Option<NetworkUpdate>, expected_short_channel_id: Option<u64>)
61+
fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(
62+
_name: &str, test_case: u8, nodes: &Vec<Node>, route: &Route, payment_hash: &PaymentHash,
63+
payment_secret: &PaymentSecret, mut callback_msg: F1, mut callback_fail: F2,
64+
mut callback_node: F3, expected_retryable: bool, expected_error_code: Option<u16>,
65+
expected_channel_update: Option<NetworkUpdate>, expected_short_channel_id: Option<u64>
66+
)
6167
where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC),
6268
F2: for <'a> FnMut(&'a mut msgs::UpdateFailHTLC),
6369
F3: FnMut(),
@@ -620,6 +626,49 @@ fn test_onion_failure() {
620626
}, ||{
621627
nodes[2].node.fail_htlc_backwards(&payment_hash);
622628
}, true, Some(23), None, None);
629+
630+
run_onion_failure_test_with_fail_intercept("bogus err packet with valid hmac", 200, &nodes,
631+
&route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
632+
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
633+
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
634+
let mut decoded_err_packet = msgs::DecodedOnionErrorPacket {
635+
failuremsg: vec![0],
636+
pad: vec![0; 255],
637+
hmac: [0; 32],
638+
};
639+
let um = onion_utils::gen_um_from_shared_secret(&onion_keys[1].shared_secret.as_ref());
640+
let mut hmac = HmacEngine::<Sha256>::new(&um);
641+
hmac.input(&decoded_err_packet.encode()[32..]);
642+
decoded_err_packet.hmac = Hmac::from_engine(hmac).into_inner();
643+
msg.reason = onion_utils::encrypt_failure_packet(
644+
&onion_keys[1].shared_secret.as_ref(), &decoded_err_packet.encode()[..])
645+
}, || nodes[2].node.fail_htlc_backwards(&payment_hash), false, None,
646+
Some(NetworkUpdate::NodeFailure { node_id: route.paths[0].hops[1].pubkey, is_permanent: true }),
647+
Some(channels[1].0.contents.short_channel_id));
648+
run_onion_failure_test_with_fail_intercept("0-length channel update in UPDATE onion failure", 200, &nodes,
649+
&route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
650+
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
651+
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
652+
let mut decoded_err_packet = msgs::DecodedOnionErrorPacket {
653+
failuremsg: vec![
654+
0x10, 0x7, // UPDATE|7
655+
0x0, 0x0 // 0-len channel update
656+
],
657+
pad: vec![0; 255 - 4 /* 4-byte error message */],
658+
hmac: [0; 32],
659+
};
660+
let um = onion_utils::gen_um_from_shared_secret(&onion_keys[1].shared_secret.as_ref());
661+
let mut hmac = HmacEngine::<Sha256>::new(&um);
662+
hmac.input(&decoded_err_packet.encode()[32..]);
663+
decoded_err_packet.hmac = Hmac::from_engine(hmac).into_inner();
664+
msg.reason = onion_utils::encrypt_failure_packet(
665+
&onion_keys[1].shared_secret.as_ref(), &decoded_err_packet.encode()[..])
666+
}, || nodes[2].node.fail_htlc_backwards(&payment_hash), true, Some(0x1000|7),
667+
Some(NetworkUpdate::ChannelFailure {
668+
short_channel_id: channels[1].0.contents.short_channel_id,
669+
is_permanent: false,
670+
}),
671+
Some(channels[1].0.contents.short_channel_id));
623672
}
624673

625674
#[test]

0 commit comments

Comments
 (0)