lightning/ln/
our_peer_storage.rs1use bitcoin::hashes::sha256::Hash as Sha256;
15use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine};
16use bitcoin::secp256k1::PublicKey;
17
18use crate::ln::types::ChannelId;
19use crate::sign::PeerStorageKey;
20
21use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
22use crate::prelude::*;
23
24pub struct DecryptedOurPeerStorage {
48 data: Vec<u8>,
49}
50
51impl DecryptedOurPeerStorage {
52 pub fn new(data: Vec<u8>) -> Self {
54 Self { data }
55 }
56
57 pub fn into_vec(self) -> Vec<u8> {
59 self.data
60 }
61
62 pub fn encrypt(self, key: &PeerStorageKey, random_bytes: &[u8; 32]) -> EncryptedOurPeerStorage {
65 let mut data = self.data;
66 let plaintext_len = data.len();
67 let nonce = derive_nonce(key, random_bytes);
68
69 let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
70 let mut tag = [0; 16];
71 chacha.encrypt_full_message_in_place(&mut data[0..plaintext_len], &mut tag);
72
73 data.extend_from_slice(&tag);
74
75 data.extend_from_slice(random_bytes);
77
78 EncryptedOurPeerStorage { cipher: data }
79 }
80}
81
82pub struct EncryptedOurPeerStorage {
89 cipher: Vec<u8>,
90}
91
92impl EncryptedOurPeerStorage {
93 const MIN_CIPHERTEXT_LEN: usize = 32 + 16;
95
96 pub fn new(cipher: Vec<u8>) -> Result<Self, ()> {
98 if cipher.len() < Self::MIN_CIPHERTEXT_LEN {
99 return Err(());
100 }
101 return Ok(Self { cipher });
102 }
103
104 pub fn into_vec(self) -> Vec<u8> {
106 self.cipher
107 }
108
109 pub fn decrypt(self, key: &PeerStorageKey) -> Result<DecryptedOurPeerStorage, ()> {
112 let mut cipher = self.cipher;
113 let cyphertext_len = cipher.len();
114
115 if cipher.len() < Self::MIN_CIPHERTEXT_LEN {
116 return Err(());
117 }
118
119 let (data_mut, random_bytes) = cipher.split_at_mut(cyphertext_len - 32);
121 let (encrypted_data, tag) = data_mut.split_at_mut(data_mut.len() - 16);
122
123 let nonce = derive_nonce(key, random_bytes);
124
125 let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
126
127 if chacha.check_decrypt_in_place(encrypted_data, tag).is_err() {
128 return Err(());
129 }
130
131 cipher.truncate(cyphertext_len - 16 - 32);
133
134 Ok(DecryptedOurPeerStorage { data: cipher })
135 }
136}
137
138fn derive_nonce(key: &PeerStorageKey, random_bytes: &[u8]) -> [u8; 12] {
140 let key_hash = Sha256::hash(&key.inner);
141
142 let mut hmac = HmacEngine::<Sha256>::new(key_hash.as_byte_array());
143 hmac.input(&random_bytes);
144 let mut nonce = [0u8; 12];
145 nonce[4..].copy_from_slice(&Hmac::from_engine(hmac).to_byte_array()[0..8]);
147
148 nonce
149}
150
151pub(crate) struct PeerStorageMonitorHolder {
162 pub(crate) channel_id: ChannelId,
164 pub(crate) counterparty_node_id: PublicKey,
166 pub(crate) min_seen_secret: u64,
168 pub(crate) monitor_bytes: Vec<u8>,
170}
171
172impl_writeable_tlv_based!(PeerStorageMonitorHolder, {
173 (0, channel_id, required),
174 (2, counterparty_node_id, required),
175 (4, min_seen_secret, required),
176 (6, monitor_bytes, required_vec),
177});
178
179#[cfg(test)]
180mod tests {
181 use crate::ln::our_peer_storage::{derive_nonce, DecryptedOurPeerStorage};
182 use crate::sign::PeerStorageKey;
183
184 #[test]
185 fn test_peer_storage_encryption_decryption() {
186 let key1 = PeerStorageKey { inner: [0u8; 32] };
187 let key2 = PeerStorageKey { inner: [1u8; 32] };
188 let random_bytes1 = [200; 32];
189 let random_bytes2 = [201; 32];
190
191 let decrypted_ops = DecryptedOurPeerStorage::new(vec![42u8; 32]);
193 let decrypted_ops_res: DecryptedOurPeerStorage =
194 decrypted_ops.encrypt(&key1, &random_bytes1).decrypt(&key1).unwrap();
195 assert_eq!(decrypted_ops_res.into_vec(), vec![42u8; 32]);
196
197 let decrypted_ops_wrong_key = DecryptedOurPeerStorage::new(vec![42u8; 32]);
199 let decrypted_ops_wrong_key_res =
200 decrypted_ops_wrong_key.encrypt(&key2, &random_bytes2).decrypt(&key1);
201 assert!(decrypted_ops_wrong_key_res.is_err());
202
203 let nonce = derive_nonce(&key1, &random_bytes1);
205 let nonce_happy_path = derive_nonce(&key1, &random_bytes1);
206 assert_eq!(nonce, nonce_happy_path);
207
208 let nonce_diff_random_bytes = derive_nonce(&key1, &random_bytes2);
210 let nonce_diff_key = derive_nonce(&key2, &random_bytes1);
211 let nonce_diff_key_random_bytes = derive_nonce(&key2, &random_bytes2);
212 assert_ne!(nonce, nonce_diff_random_bytes);
213 assert_ne!(nonce, nonce_diff_key);
214 assert_ne!(nonce, nonce_diff_key_random_bytes);
215 }
216}