-
Notifications
You must be signed in to change notification settings - Fork 417
Introduce ReceiveAuthKey #3917
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Introduce ReceiveAuthKey #3917
Conversation
I've assigned @valentinewallace as a reviewer! |
cc @TheBlueMatt |
`Poly1305::raw_result` copies the output into a slice, for some reason allowing any length sice. This isn't a great API, so while we're here we change it to return the 16-byte tag instead.
Rather than skipping compilation of `poly1305.rs` when building for fuzzing and relying on `ChaCha20Poly1305` to do the fuzzing variants, implement an actual fuzz wrapper in `poly1305.rs`, keeping the same fuzz MAC structure that we already have. We also add a fuzzing implementation of `fixed_time_eq` which does a simple comparison, to allow the fuzzer to "see into" the comparison in some cases. Best reviewed with `-b`.
`ChaChaPolyReadAdapter` decodes an arbitrary object and checks the poly1305 tag. In the coming commits, we'll need a variant of this which allows for an *optional* AAD in the poly1305 tag, accepting either tag as valid, but indicating to the caller whether the AAD was used. We could use the actual AAD setup in poly1305, which puts the AAD first in the MAC (and then pads it out to a multiple of 16 bytes), but since we're gonna check both with and without, its nice to instead put the AAD at the end, enabling us to only calculate most of the hash once before cloning its state and adding the AAD block. We do this by swapping the AAD and the data being MAC'd in the AAD-containing MAC check (but leaving them where they belong for the non-AAD-containing MAC check). We also add a corresponding `chachapoly_encrypt_with_swapped_aad` which allows encrypting with the new MAC format.
When we receive an onion message, we often want to make sure it was sent through a blinded path we constructed. This protects us from various deanonymization attacks where someone can send a message to every node on the network until they find us, effectively unwrapping the blinded path and identifying its recipient. We generally do so by adding authentication tags to our `MessageContext` variants. Because the contexts themselves are encrypted (and MAC'd) to us, we only have to ensure that they cannot be forged, which is trivially accomplished with a simple nonce and a MAC covering it. This logic has ended up being repeated in nearly all of our onion message handlers, and has gotten quite repetitive. Instead, here, we simply authenticate the blinded path contexts using the MAC that's already there, but tweaking it with an additional secret as the AAD in Poly1305. This prevents forgery as the secret is now required to make the MAC check pass. Ultimately this means that no one can ever build a blinded path which terminates at an LDK node that we'll accept, but over time we've come to recognize this as a useful property, rather than something to fight. Here we finally break from the spec fully in our context encryption (not just the contents thereof). This will save a bit of space in some of our `MessageContext`s, though sadly not in the blinded path we include in `Bolt12Offer`s, so they're generally not in space-sensitive blinded paths. We can apply the same logic in our blinded payment paths as well, but we do not do so here. This commit only adds the required changes to the cryptography, for now it uses a constant key of `[41; 32]`.
This commit replaces the hardcoded key used for authenticating the context in incoming `BlindedMessagePath`s with a dedicated `ReceiveAuthKey`. This makes the authentication mechanism explicit and configurable for the user. Changes include: - Introducing `ReceiveAuthKey` to the `NodeSigner`, used to authenticate the context at the final hop of an incoming blinded path. - Updating `BlindedMessagePath::new` to accept a `ReceiveAuthKey` as a parameter during path construction.
Now that we have introduced an alternate mechanism for authentication in the codebase, we can safely remove the now redundant (hmac, nonce) fields from the MessageContext's while maintaining the security of the onion messages.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3917 +/- ##
==========================================
+ Coverage 88.85% 88.86% +0.01%
==========================================
Files 166 166
Lines 119438 119602 +164
Branches 119438 119602 +164
==========================================
+ Hits 106129 106290 +161
Misses 10985 10985
- Partials 2324 2327 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically LGTM, a few minor nits.
Also, the last commit is beautiful:
4 files changed, 34 insertions(+), 331 deletions(-)
pub struct ReceiveAuthKey { | ||
/// Represents the key used to authenticate incoming [`BlindedMessagePath`]s. | ||
/// | ||
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath | ||
pub inner: [u8; 32], | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If its just wrapping an inner and that won't change, usually its better to define it as a tuple, ie pub struct ReceiveAuthKey(pub [u8; 32])
@@ -93,7 +93,7 @@ impl BlindedMessagePath { | |||
recipient_node_id, | |||
context, | |||
&blinding_secret, | |||
[41; 32], // TODO: Pass this in | |||
ReceiveAuthKey { inner: [41; 32] }, // TODO: Pass this in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, but we should redo the commit ordering instead of changing code added in the previous commit. If you break this commit into two - one that just adds the type and then one that contains the rest, you should be able to move the commit that just adds the type earlier in the commit history, then squash the commit that contains the rest into my commit (changing the author to you and leaving a Co-authored-by
tag at the end of the commit message).
const OFFER_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[5; 16]; | ||
// HMAC input for a `PaymentId`. The HMAC is used in `AsyncPaymentsContext::OutboundPayment`. | ||
#[cfg(async_payments)] | ||
const ASYNC_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[6; 16]; | ||
|
||
// HMAC input for a `PaymentHash`. The HMAC is used in `OffersContext::InboundPayment`. | ||
const PAYMENT_HASH_HMAC_INPUT: &[u8; 16] = &[7; 16]; | ||
|
||
// HMAC input for `ReceiveTlvs`. The HMAC is used in `blinded_path::payment::PaymentContext`. | ||
const PAYMENT_TLVS_HMAC_INPUT: &[u8; 16] = &[8; 16]; | ||
|
||
// HMAC input used in `AsyncPaymentsContext::InboundPayment` to authenticate inbound | ||
// held_htlc_available onion messages. | ||
#[cfg(async_payments)] | ||
const ASYNC_PAYMENTS_HELD_HTLC_HMAC_INPUT: &[u8; 16] = &[9; 16]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should leave comments noting the HMAC_INPUTs that were previously used for other purposes so we never reuse them again.
Builds on #3845
This PR builds on the work in #3845 by introducing
ReceiveAuthKey
, a dedicated struct that replaces the previously hardcoded[u8; 32]
used for authenticatingMessageContext
s in incomingBlindedMessagePath
s.It:
ReceiveAuthKey
structNodeSigner
interfaceBlindedMessagePath
constructor to accept it as a parameterThis completes the original intent of #3845 — making the authentication mechanism explicit and less byte-heavy, while preserving the same security properties.
Next steps:
(HMAC, Nonce)
pair from relevantMessageContext
variants