Skip to content

Commit ed58827

Browse files
committed
fixup: Add OurPeerStorage for serialized Peer Storage backups
1 parent 1cdd004 commit ed58827

File tree

1 file changed

+88
-94
lines changed

1 file changed

+88
-94
lines changed

lightning/src/ln/our_peer_storage.rs

Lines changed: 88 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
// You may not use this file except in accordance with one or both of these
88
// licenses.
99

10-
//! `OurPeerStorage` enables storage of encrypted serialized channel data.
11-
//! It provides encryption and decryption of data to maintain data integrity and
10+
//! `DecryptedOurPeerStorage` enables storage of encrypted serialized channel data.
11+
//! It provides encryption of data to maintain data integrity and
1212
//! security during transmission.
13-
//!
1413
1514
use bitcoin::hashes::sha256::Hash as Sha256;
1615
use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine};
@@ -20,113 +19,111 @@ use crate::sign::PeerStorageKey;
2019
use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
2120
use crate::prelude::*;
2221

23-
/// [`OurPeerStorage`] is used to store encrypted channel information that allows for the creation of a
22+
/// [`DecryptedOurPeerStorage`] is used to store serialised channel information that allows for the creation of a
2423
/// `peer_storage` backup.
2524
///
2625
/// This structure is designed to serialize channel data for backup and supports encryption
27-
/// and decryption using `ChaCha20Poly1305RFC` for transmission.
26+
/// using `ChaCha20Poly1305RFC` for transmission.
2827
///
2928
/// # Key Methods
30-
/// - [`OurPeerStorage::new`]: Returns [`OurPeerStorage`] with the given encrypted_data.
31-
/// - [`OurPeerStorage::create_from_data`]: Returns [`OurPeerStorage`] created from encrypting the provided data.
32-
/// - [`OurPeerStorage::decrypt_our_peer_storage`]: Decrypts the [`OurPeerStorage::encrypted_data`] using the key and returns decrypted data.
29+
/// - [`DecryptedOurPeerStorage::new`]: Returns [`DecryptedOurPeerStorage`] with the given data.
30+
/// - [`DecryptedOurPeerStorage::encrypt`]: Returns [`EncryptedOurPeerStorage`] created from encrypting the provided data.
31+
/// - [`DecryptedOurPeerStorage::into_vec`]: Returns the data in [`Vec<u8>`] format.
3332
///
3433
/// ## Example
3534
/// ```
36-
/// use lightning::ln::our_peer_storage::OurPeerStorage;
35+
/// use lightning::ln::our_peer_storage::DecryptedOurPeerStorage;
3736
/// use lightning::sign::PeerStorageKey;
3837
/// let key = PeerStorageKey{inner: [0u8; 32]};
39-
/// let decrypted_ops = OurPeerStorage::DecryptedPeerStorage { data: vec![1, 2, 3]};
40-
/// let our_peer_storage = decrypted_ops.encrypt_peer_storage(&key, [0u8; 32]);
41-
/// let decrypted_data = our_peer_storage.decrypt_peer_storage(&key).unwrap();
38+
/// let decrypted_ops = DecryptedOurPeerStorage::new(vec![1, 2, 3]);
39+
/// let our_peer_storage = decrypted_ops.encrypt(&key, [0u8; 32]);
40+
/// let decrypted_data = our_peer_storage.decrypt(&key).unwrap();
4241
/// assert_eq!(decrypted_data.into_vec(), vec![1, 2, 3]);
4342
/// ```
44-
#[derive(PartialEq, Eq, Debug)]
45-
pub enum OurPeerStorage {
46-
/// Contains ciphertext for transmission.
47-
EncryptedPeerStorage {
48-
/// Stores ciphertext.
49-
cipher: Vec<u8>,
50-
},
51-
/// Contains serialised decrypted peer storage backup.
52-
DecryptedPeerStorage {
53-
/// Stores decrypted serialised data.
54-
data: Vec<u8>,
55-
},
43+
pub struct DecryptedOurPeerStorage {
44+
data: Vec<u8>,
5645
}
5746

58-
impl OurPeerStorage {
59-
/// Return [`OurPeerStorage::EncryptedPeerStorage`] or [`OurPeerStorage::DecryptedPeerStorage`]
60-
/// in [`Vec<u8>`] form.
47+
impl DecryptedOurPeerStorage {
48+
/// Returns [`DecryptedOurPeerStorage`] with the given data.
49+
pub fn new(data: Vec<u8>) -> Self {
50+
Self { data }
51+
}
52+
53+
/// Returns data stored in [`Vec<u8>`] format.
6154
pub fn into_vec(self) -> Vec<u8> {
62-
match self {
63-
OurPeerStorage::DecryptedPeerStorage { data } => data,
64-
OurPeerStorage::EncryptedPeerStorage { cipher } => cipher,
65-
}
55+
self.data
6656
}
6757

68-
/// Returns [`OurPeerStorage::EncryptedPeerStorage`] with encrypted `cipher`.
69-
///
70-
/// This function takes a `key` (for encryption) and random_bytes (to derive nonce for encryption)
71-
/// and returns a [`OurPeerStorage::EncryptedPeerStorage`] with encrypted data inside.
72-
/// It should only be called on [`OurPeerStorage::DecryptedPeerStorage`] otherwise it would panic.
73-
///
74-
/// The resulting serialised data is intended to be directly used for transmission to the peers.
75-
pub fn encrypt_peer_storage(
76-
self, key: &PeerStorageKey, random_bytes: [u8; 32],
77-
) -> OurPeerStorage {
78-
match self {
79-
OurPeerStorage::DecryptedPeerStorage { mut data } => {
80-
let plaintext_len = data.len();
81-
let nonce = derive_nonce(key, &random_bytes);
82-
83-
let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
84-
let mut tag = [0; 16];
85-
chacha.encrypt_full_message_in_place(&mut data[0..plaintext_len], &mut tag);
86-
87-
data.extend_from_slice(&tag);
88-
89-
// Prepend `random_bytes` in front of the encrypted_blob.
90-
data.splice(0..0, random_bytes);
91-
Self::EncryptedPeerStorage { cipher: data }
92-
},
93-
OurPeerStorage::EncryptedPeerStorage { cipher: _ } => {
94-
panic!("Expected OurPeerStorage::DecryptedPeerStorage!");
95-
},
96-
}
58+
/// Encrypts the data inside [`DecryptedOurPeerStorage`] using [`PeerStorageKey`] and `random_bytes`
59+
/// and returns [`EncryptedOurPeerStorage`].
60+
pub fn encrypt(self, key: &PeerStorageKey, random_bytes: [u8; 32]) -> EncryptedOurPeerStorage {
61+
let mut data = self.data;
62+
let plaintext_len = data.len();
63+
let nonce = derive_nonce(key, &random_bytes);
64+
65+
let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
66+
let mut tag = [0; 16];
67+
chacha.encrypt_full_message_in_place(&mut data[0..plaintext_len], &mut tag);
68+
69+
data.extend_from_slice(&tag);
70+
71+
// Prepend `random_bytes` in front of the encrypted_blob.
72+
data.splice(0..0, random_bytes);
73+
74+
EncryptedOurPeerStorage { cipher: data }
9775
}
76+
}
77+
78+
/// [`EncryptedOurPeerStorage`] represents encrypted state of the corresponding [`DecryptedOurPeerStorage`].
79+
///
80+
/// # Key Methods
81+
/// - [`EncryptedOurPeerStorage::new`]: Returns [`EncryptedOurPeerStorage`] with the given encrypted cipher.
82+
/// - [`EncryptedOurPeerStorage::decrypt`]: Returns [`DecryptedOurPeerStorage`] created from decrypting the cipher.
83+
/// - [`EncryptedOurPeerStorage::into_vec`]: Returns the cipher in [`Vec<u8>`] format.
84+
pub struct EncryptedOurPeerStorage {
85+
cipher: Vec<u8>,
86+
}
9887

99-
/// This expects a [`OurPeerStorage::EncryptedPeerStorage`] which would be consumed
100-
/// to return a [`OurPeerStorage::DecryptedPeerStorage`] in case of successful decryption.
101-
///
102-
/// It would return error if the ciphertext inside [`OurPeerStorage::EncryptedPeerStorage`] is
103-
/// not correct and panic if it is called on [`OurPeerStorage::DecryptedPeerStorage`].
104-
pub fn decrypt_peer_storage(self, key: &PeerStorageKey) -> Result<Self, ()> {
105-
match self {
106-
OurPeerStorage::EncryptedPeerStorage { mut cipher } => {
107-
let cyphertext_len = cipher.len();
88+
impl EncryptedOurPeerStorage {
89+
/// Returns [`EncryptedOurPeerStorage`] if cipher is of appropriate length, else returns error.
90+
pub fn new(cipher: Vec<u8>) -> Result<Self, ()> {
91+
// Ciphertext is of the form: random_bytes(32 bytes) + encrypted_data + tag(16 bytes).
92+
const MIN_CIPHERTEXT_LEN: usize = 32 + 16;
93+
94+
if cipher.len() < MIN_CIPHERTEXT_LEN {
95+
return Err(());
96+
}
97+
return Ok(Self { cipher });
98+
}
10899

109-
// Ciphertext is of the form: random_bytes(32 bytes) + encrypted_data + tag(16 bytes).
110-
let (data_mut, tag) = cipher.split_at_mut(cyphertext_len - 16);
111-
let (random_bytes, encrypted_data) = data_mut.split_at_mut(32);
100+
/// Returns cipher in the format [`Vec<u8>`].
101+
pub fn into_vec(self) -> Vec<u8> {
102+
self.cipher
103+
}
112104

113-
let nonce = derive_nonce(key, random_bytes);
105+
/// Returns [`DecryptedOurPeerStorage`] if it successfully decrypts the ciphertext with the `key`,
106+
/// else returns error.
107+
pub fn decrypt(self, key: &PeerStorageKey) -> Result<DecryptedOurPeerStorage, ()> {
108+
let mut cipher = self.cipher;
109+
let cyphertext_len = cipher.len();
114110

115-
let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
111+
// Ciphertext is of the form: random_bytes(32 bytes) + encrypted_data + tag(16 bytes).
112+
let (data_mut, tag) = cipher.split_at_mut(cyphertext_len - 16);
113+
let (random_bytes, encrypted_data) = data_mut.split_at_mut(32);
116114

117-
if chacha.check_decrypt_in_place(encrypted_data, tag).is_err() {
118-
return Err(());
119-
}
115+
let nonce = derive_nonce(key, random_bytes);
120116

121-
cipher.truncate(cyphertext_len - 16);
122-
cipher.drain(0..32);
117+
let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
123118

124-
Ok(Self::DecryptedPeerStorage { data: cipher })
125-
},
126-
OurPeerStorage::DecryptedPeerStorage { data: _ } => {
127-
panic!("Expected OurPeerStorage::EncryptedPeerStorage!");
128-
},
119+
if chacha.check_decrypt_in_place(encrypted_data, tag).is_err() {
120+
return Err(());
129121
}
122+
123+
cipher.truncate(cyphertext_len - 16);
124+
cipher.drain(0..32);
125+
126+
Ok(DecryptedOurPeerStorage { data: cipher })
130127
}
131128
}
132129

@@ -145,7 +142,7 @@ fn derive_nonce(key: &PeerStorageKey, random_bytes: &[u8]) -> [u8; 12] {
145142

146143
#[cfg(test)]
147144
mod tests {
148-
use crate::ln::our_peer_storage::{derive_nonce, OurPeerStorage};
145+
use crate::ln::our_peer_storage::{derive_nonce, DecryptedOurPeerStorage};
149146
use crate::sign::PeerStorageKey;
150147

151148
#[test]
@@ -156,18 +153,15 @@ mod tests {
156153
let random_bytes2 = [201; 32];
157154

158155
// Happy Path
159-
let decrypted_ops = OurPeerStorage::DecryptedPeerStorage { data: vec![42u8; 32] };
160-
let decrypted_ops_res = decrypted_ops
161-
.encrypt_peer_storage(&key1, random_bytes1)
162-
.decrypt_peer_storage(&key1)
163-
.unwrap();
156+
let decrypted_ops = DecryptedOurPeerStorage::new(vec![42u8; 32]);
157+
let decrypted_ops_res: DecryptedOurPeerStorage =
158+
decrypted_ops.encrypt(&key1, random_bytes1).decrypt(&key1).unwrap();
164159
assert_eq!(decrypted_ops_res.into_vec(), vec![42u8; 32]);
165160

166161
// Changing Key
167-
let decrypted_ops_wrong_key = OurPeerStorage::DecryptedPeerStorage { data: vec![42u8; 32] };
168-
let decrypted_ops_wrong_key_res = decrypted_ops_wrong_key
169-
.encrypt_peer_storage(&key2, random_bytes2)
170-
.decrypt_peer_storage(&key1);
162+
let decrypted_ops_wrong_key = DecryptedOurPeerStorage::new(vec![42u8; 32]);
163+
let decrypted_ops_wrong_key_res =
164+
decrypted_ops_wrong_key.encrypt(&key2, random_bytes2).decrypt(&key1);
171165
assert!(decrypted_ops_wrong_key_res.is_err());
172166

173167
// Nonce derivation happy path

0 commit comments

Comments
 (0)