Unify and simplify the application of simple chacha20 passes
What changed, and why it matters
This commit is a code cleanup: it moves repeated ChaCha20 encryption calls into a single helper function without changing the underlying math or behavior. There is no indication it fixes a security bug or introduces a new vulnerability.
No security action required. Treat as normal code-quality review; verify tests still pass and that the helper is used consistently.
Security signals we found
Refactor only: identical ChaCha20 construction moved to helper
No change to key, nonce, or counter derivation
No new unwraps introduced; existing unwraps consolidated
No vendor disclosure or advisory references present
Evidence from the diff
The change unifies multiple inline ChaCha20::new_from_block calls into a new apply_chacha20 helper in lightning/src/crypto/utils.rs. The helper still constructs the same key, nonce, and block counter from the same byte slices and calls apply_keystream. The refactor removes duplicated unwrap/try_into logic but preserves the exact same cryptographic construction. No algorithmic change, no new dependencies, and no security-relevant behavioral difference is visible in the diff.
Changed components
lightning/src/crypto/utils.rslightning/src/ln/inbound_payment.rslightning/src/sign/mod.rsInspect captured patch +23 / −58
diff --git a/lightning/src/crypto/utils.rs b/lightning/src/crypto/utils.rs
index 749f7d4..d6fa204 100644
--- a/lightning/src/crypto/utils.rs
+++ b/lightning/src/crypto/utils.rs
@@ -3,6 +3,8 @@ use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::{Hash, HashEngine};
use bitcoin::secp256k1::{ecdsa::Signature, Message, Secp256k1, SecretKey, Signing};
+use chacha20_poly1305::chacha20::{ChaCha20, Key, Nonce};
+
use crate::sign::EntropySource;
macro_rules! hkdf_extract_expand {
@@ -96,3 +98,12 @@ pub fn sign_with_aux_rand<C: Signing, ES: EntropySource>(
let sig = sign(ctx, msg, sk);
sig
}
+
+pub fn apply_chacha20(key: [u8; 32], nonce: [u8; 16], data: &mut [u8]) {
+ ChaCha20::new_from_block(
+ Key::new(key),
+ Nonce::new(nonce[4..].try_into().unwrap()),
+ u32::from_le_bytes(nonce[..4].try_into().unwrap()),
+ )
+ .apply_keystream(data);
+}
diff --git a/lightning/src/ln/inbound_payment.rs b/lightning/src/ln/inbound_payment.rs
index 40b0477..077d2df 100644
--- a/lightning/src/ln/inbound_payment.rs
+++ b/lightning/src/ln/inbound_payment.rs
@@ -13,9 +13,8 @@ use bitcoin::hashes::cmp::fixed_time_eq;
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::{Hash, HashEngine};
-use chacha20_poly1305::chacha20::{ChaCha20, Key, Nonce};
-use crate::crypto::utils::hkdf_extract_expand_8x;
+use crate::crypto::utils::{apply_chacha20, hkdf_extract_expand_8x};
use crate::ln::msgs;
use crate::ln::msgs::MAX_VALUE_MSAT;
use crate::offers::nonce::Nonce as LocalNonce;
@@ -101,12 +100,7 @@ impl ExpandedKey {
/// Encrypts or decrypts the given `bytes`. Used for data included in an offer message's
/// metadata (e.g., payment id).
pub(crate) fn crypt_for_offer(&self, mut bytes: [u8; 32], nonce: LocalNonce) -> [u8; 32] {
- ChaCha20::new_from_block(
- Key::new(self.offers_encryption_key),
- Nonce::new(nonce.0[4..].try_into().unwrap()),
- u32::from_le_bytes(nonce.0[..4].try_into().unwrap()),
- )
- .apply_keystream(&mut bytes);
+ apply_chacha20(self.offers_encryption_key, nonce.0, &mut bytes);
bytes
}
}
@@ -181,12 +175,7 @@ pub fn create<ES: EntropySource>(
iv_bytes.copy_from_slice(&rand_bytes[..IV_LEN]);
if let Some(metadata) = payment_metadata.as_mut() {
- ChaCha20::new_from_block(
- Key::new(keys.metadata_enc_key),
- Nonce::new(iv_bytes[4..].try_into().unwrap()),
- u32::from_le_bytes(iv_bytes[..4].try_into().unwrap()),
- )
- .apply_keystream(metadata.as_mut_slice());
+ apply_chacha20(keys.metadata_enc_key, iv_bytes, metadata.as_mut_slice());
}
let mut hmac = HmacEngine::<Sha256>::new(&keys.ldk_pmt_hash_key);
@@ -238,12 +227,7 @@ pub fn create_from_hash<ES: EntropySource>(
let rand_bytes = entropy_source.get_secure_random_bytes();
iv_bytes.copy_from_slice(&rand_bytes[..IV_LEN]);
- ChaCha20::new_from_block(
- Key::new(keys.metadata_enc_key),
- Nonce::new(iv_bytes[4..16].try_into().unwrap()),
- u32::from_le_bytes(iv_bytes[..4].try_into().unwrap()),
- )
- .apply_keystream(metadata.as_mut_slice());
+ apply_chacha20(keys.metadata_enc_key, iv_bytes, metadata.as_mut_slice());
metadata.extend_from_slice(&iv_bytes);
}
@@ -349,12 +333,7 @@ fn construct_payment_secret(
iv_slice.copy_from_slice(iv_bytes);
encrypted_info_slice.copy_from_slice(info_bytes);
- ChaCha20::new_from_block(
- Key::new(*info_key),
- Nonce::new(iv_bytes[4..].try_into().unwrap()),
- u32::from_le_bytes(iv_bytes[..4].try_into().unwrap()),
- )
- .apply_keystream(encrypted_info_slice);
+ apply_chacha20(*info_key, *iv_bytes, encrypted_info_slice);
PaymentSecret(payment_secret_bytes)
}
@@ -442,13 +421,9 @@ pub(super) fn verify<L: Logger>(
}
let new_len = metadata.len() - IV_LEN;
let (metadata_enc, metadata_iv) = metadata.split_at_mut(new_len);
+ let metadata_iv: [u8; IV_LEN] = metadata_iv.try_into().expect("len checked");
- ChaCha20::new_from_block(
- Key::new(keys.metadata_enc_key),
- Nonce::new(metadata_iv[4..16].try_into().unwrap()),
- u32::from_le_bytes(metadata_iv[..4].try_into().unwrap()),
- )
- .apply_keystream(metadata_enc);
+ apply_chacha20(keys.metadata_enc_key, metadata_iv, metadata_enc);
metadata.truncate(new_len);
}
},
@@ -473,12 +448,7 @@ pub(super) fn verify<L: Logger>(
}
if let Some(metadata) = payment_metadata {
- ChaCha20::new_from_block(
- Key::new(keys.metadata_enc_key),
- Nonce::new(iv_bytes[4..].try_into().unwrap()),
- u32::from_le_bytes(iv_bytes[..4].try_into().unwrap()),
- )
- .apply_keystream(metadata);
+ apply_chacha20(keys.metadata_enc_key, iv_bytes, metadata);
}
},
Ok(Method::SpontaneousPayment) => {
@@ -557,12 +527,7 @@ pub(super) fn get_payment_preimage(
})?;
if let Some(metadata) = payment_metadata {
- ChaCha20::new_from_block(
- Key::new(keys.metadata_enc_key),
- Nonce::new(iv_bytes[4..].try_into().unwrap()),
- u32::from_le_bytes(iv_bytes[..4].try_into().unwrap()),
- )
- .apply_keystream(metadata);
+ apply_chacha20(keys.metadata_enc_key, iv_bytes, metadata);
}
Ok(preimage)
},
@@ -590,12 +555,7 @@ fn decrypt_info(
let mut info_bytes: [u8; INFO_LEN] = [0; INFO_LEN];
info_bytes.copy_from_slice(encrypted_info_bytes);
- ChaCha20::new_from_block(
- Key::new(keys.info_key),
- Nonce::new(iv_bytes[4..].try_into().unwrap()),
- u32::from_le_bytes(iv_bytes[..4].try_into().unwrap()),
- )
- .apply_keystream(&mut info_bytes);
+ apply_chacha20(keys.info_key, iv_bytes, &mut info_bytes);
(iv_bytes, info_bytes)
}
diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs
index a3dc720..3adc638 100644
--- a/lightning/src/sign/mod.rs
+++ b/lightning/src/sign/mod.rs
@@ -34,12 +34,11 @@ use bitcoin::secp256k1::schnorr;
use bitcoin::secp256k1::All;
use bitcoin::secp256k1::{Keypair, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
use bitcoin::{secp256k1, Psbt, Sequence, Txid, WPubkeyHash, Witness};
-use chacha20_poly1305::chacha20::{ChaCha20, Key, Nonce};
use lightning_invoice::RawBolt11Invoice;
use crate::chain::transaction::OutPoint;
-use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
+use crate::crypto::utils::{apply_chacha20, hkdf_extract_expand_twice, sign, sign_with_aux_rand};
use crate::ln::chan_utils;
use crate::ln::chan_utils::{
get_countersigner_payment_script, get_revokeable_redeemscript, make_funding_redeemscript,
@@ -2704,12 +2703,7 @@ impl EntropySource for RandomBytes {
let mut nonce = [0u8; 16];
nonce[..8].copy_from_slice(&index.to_be_bytes());
let mut chacha_bytes = [0; 32];
- ChaCha20::new_from_block(
- Key::new(self.seed),
- Nonce::new(nonce[4..].try_into().unwrap()),
- u32::from_le_bytes(nonce[..4].try_into().unwrap()),
- )
- .apply_keystream(&mut chacha_bytes);
+ apply_chacha20(self.seed, nonce, &mut chacha_bytes);
chacha_bytes
}
}
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.