Skip to content

Commit f4bac86

Browse files
committed
Add OurPeerStorage for serialized Peer Storage backups
Introduce the OurPeerStorage struct to manage serialized channel data for peer storage backups. This struct facilitates the distribution of peer storage to channel partners and includes versioning and timestamping for comparison between retrieved peer storage instances. - Add the OurPeerStorage struct with fields for version, timestamp, and serialized channel data (ser_channels). - Implement methods to encrypt and decrypt peer storage securely. - Add functionality to update channel data within OurPeerStorage.
1 parent 0468fce commit f4bac86

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

lightning/src/ln/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub mod chan_utils;
2424
mod features;
2525
pub mod script;
2626
pub mod types;
27+
pub mod our_peer_storage;
2728

2829
// TODO: These modules were moved from lightning-invoice and need to be better integrated into this
2930
// crate now:
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// This file is Copyright its original authors, visible in version control
2+
// history.
3+
//
4+
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5+
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7+
// You may not use this file except in accordance with one or both of these
8+
// licenses.
9+
10+
//! `OurPeerStorage` enables versioned storage of serialized channel data.
11+
//! It supports encryption and decryption to maintain data integrity and security during
12+
//! transmission.
13+
14+
use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
15+
use crate::prelude::*;
16+
17+
/// [`OurPeerStorage`] is used to store channel information that allows for the creation of a
18+
/// `peer_storage` backup. It includes versioning and timestamping for comparison between
19+
/// instances of [`OurPeerStorage`].
20+
///
21+
/// This structure is designed to serialize channel data for backup and supports encryption
22+
/// and decryption to ensure data integrity and security during exchange or storage.
23+
///
24+
/// # Key Methods
25+
/// - `create_from_data`: Returns an encrypted [`OurPeerStorage`] instance created from the provided data.
26+
/// - `decrypt_our_peer_storage`: Decrypts the [`OurPeerStorage::encrypted_data`] using the key and returns decrypted data.
27+
///
28+
/// # Usage
29+
/// This structure can be used for securely managing and exchanging peer storage backups. It
30+
/// includes methods for encryption and decryption using `ChaCha20Poly1305RFC`, making it
31+
/// suitable for on-the-wire transmission.
32+
///
33+
/// ## Example
34+
/// ```ignore
35+
/// let key = [0u8; 32];
36+
/// let our_peer_storage = OurPeerStorage::create_from_data(key.clone(), vec![1,2,3]);
37+
/// let decrypted_data = our_peer_storage.decrypt_our_peer_storage(key).unwrap();
38+
/// assert_eq!(decrypted_data, vec![1 , 2, 3]);
39+
/// ```
40+
#[derive(PartialEq)]
41+
pub struct OurPeerStorage {
42+
encrypted_data: Vec<u8>,
43+
}
44+
45+
impl OurPeerStorage {
46+
/// Creates a new [`OurPeerStorage`] with given encrypted_data.
47+
pub fn new(encrypted_data: Vec<u8>) -> Self {
48+
Self { encrypted_data }
49+
}
50+
51+
/// Get encrypted data stored inside [`OurPeerStorage`].
52+
pub fn encrypted_data(&self) -> Vec<u8> {
53+
self.encrypted_data.clone()
54+
}
55+
56+
/// Creates a serialised representation of [`OurPeerStorage`] from the given `ser_channels` data.
57+
///
58+
/// This function takes a `key` (for encryption) and `ser_channels` data
59+
/// (serialised channel information), and returns a serialised [`OurPeerStorage`] as a `Vec<u8>`.
60+
///
61+
/// The resulting serialised data is intended to be directly used for transmission to the peers.
62+
pub fn create_from_data(key: [u8; 32], mut ser_channels: Vec<u8>) -> OurPeerStorage {
63+
let n = 0u64;
64+
65+
let plaintext_len = ser_channels.len();
66+
67+
let mut nonce = [0; 12];
68+
nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
69+
70+
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, b"");
71+
let mut tag = [0; 16];
72+
chacha.encrypt_full_message_in_place(&mut ser_channels[0..plaintext_len], &mut tag);
73+
74+
ser_channels.extend_from_slice(&tag);
75+
76+
Self { encrypted_data: ser_channels }
77+
}
78+
79+
/// Decrypt `OurPeerStorage` using the `key`, result is stored inside the `res`.
80+
/// Returns an error if the the `cyphertext` is not correct.
81+
pub fn decrypt_our_peer_storage(mut self, key: [u8; 32]) -> Result<Vec<u8>, ()> {
82+
const MIN_CYPHERTEXT_LEN: usize = 16;
83+
let cyphertext_len = self.encrypted_data.len();
84+
85+
// Split the cyphertext into the encrypted data and the authentication tag.
86+
let (encrypted_data, tag) = self.encrypted_data.split_at_mut(cyphertext_len - 16);
87+
88+
// Ensure the cyphertext is at least as large as the MIN_CYPHERTEXT_LEN.
89+
if cyphertext_len < MIN_CYPHERTEXT_LEN {
90+
return Err(());
91+
}
92+
93+
let n = 0u64;
94+
let mut nonce = [0; 12];
95+
nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
96+
97+
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, b"");
98+
99+
if chacha.check_decrypt_in_place(encrypted_data, tag).is_err() {
100+
return Err(());
101+
}
102+
103+
Ok(encrypted_data.to_vec())
104+
}
105+
}

0 commit comments

Comments
 (0)