Skip to content

Commit 3778b81

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 b133e80 commit 3778b81

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-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:

lightning/src/ln/our_peer_storage.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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 and timestamped 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+
16+
use crate::util::ser::{Readable, VecWriter, Writeable, Writer};
17+
18+
use crate::io::{self, Error};
19+
use crate::prelude::*;
20+
21+
use crate::ln::msgs::DecodeError;
22+
23+
/// [`OurPeerStorage`] is used to store channel information that allows for the creation of a
24+
/// `peer_storage` backup. It includes versioning and timestamping for comparison between
25+
/// instances of [`OurPeerStorage`].
26+
///
27+
/// This structure is designed to serialize channel data for backup and supports encryption
28+
/// and decryption to ensure data integrity and security during exchange or storage.
29+
///
30+
/// # Key Methods
31+
/// - `create_from_data`: Returns an encrypted PeerStorage instance created from the provided data.
32+
/// - `get_ser_channels`: Retrieves the serialized channel data.
33+
/// - `decrypt_our_peer_storage`: Decrypts the ciphertext using the key and updates the result buffer.
34+
///
35+
/// # Usage
36+
/// This structure can be used for securely managing and exchanging peer storage backups. It
37+
/// includes methods for encryption and decryption using `ChaCha20Poly1305RFC`, making it
38+
/// suitable for on-the-wire transmission.
39+
///
40+
/// ## Example
41+
/// ```ignore
42+
/// let key = [0u8; 32];
43+
/// let mut our_peer_storage = OurPeerStorage::create_from_data(key.clone(), vec![1,2,3]);
44+
/// let mut decrypted = vec![0u8; encrypted.len()];
45+
/// OurPeerStorage::decrypt_our_peer_storage(&mut decrypted, &our_peer_storage, key).unwrap();
46+
/// ```
47+
#[derive(PartialEq)]
48+
pub struct OurPeerStorage {
49+
version: u8,
50+
ser_channels: Vec<u8>,
51+
}
52+
53+
impl OurPeerStorage {
54+
/// Get `ser_channels` field from [`OurPeerStorage`]
55+
pub fn get_ser_channels(&self) -> Vec<u8> {
56+
self.ser_channels.clone()
57+
}
58+
59+
/// Create serialised [`OurPeerStorage`] from the given ser_channels data.
60+
pub fn create_from_data(key: [u8; 32], ser_channels: Vec<u8>) -> Vec<u8> {
61+
let our_peer_storage = Self {
62+
version: 1,
63+
ser_channels,
64+
};
65+
66+
let n = 0u64;
67+
let mut peer_storage = VecWriter(Vec::new());
68+
our_peer_storage.write(&mut peer_storage).unwrap();
69+
let mut res = vec![0; peer_storage.0.len() + 16];
70+
71+
let plaintext = &peer_storage.0[..];
72+
let mut nonce = [0; 12];
73+
nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
74+
75+
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, b"");
76+
let mut tag = [0; 16];
77+
chacha.encrypt(plaintext, &mut res[0..plaintext.len()], &mut tag);
78+
res[plaintext.len()..].copy_from_slice(&tag);
79+
res
80+
}
81+
82+
/// Decrypt `OurPeerStorage` using the `key`, result is stored inside the `res`.
83+
/// Returns an error if the the `cyphertext` is not correct.
84+
pub fn decrypt_our_peer_storage(res: &mut [u8], cyphertext: &[u8], key: [u8; 32]) -> Result<(), ()> {
85+
const MIN_CYPHERTEXT_LEN: usize = 16;
86+
87+
// Ensure the cyphertext is at least as large as the MIN_CYPHERTEXT_LEN.
88+
if cyphertext.len() < MIN_CYPHERTEXT_LEN {
89+
return Err(());
90+
}
91+
92+
let n = 0u64;
93+
let mut nonce = [0; 12];
94+
nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
95+
96+
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, b"");
97+
if chacha
98+
.variable_time_decrypt(
99+
&cyphertext[0..cyphertext.len() - 16],
100+
res,
101+
&cyphertext[cyphertext.len() - 16..],
102+
)
103+
.is_err()
104+
{
105+
return Err(());
106+
}
107+
Ok(())
108+
}
109+
}
110+
111+
impl Writeable for OurPeerStorage {
112+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
113+
write_ver_prefix!(writer, self.version, 1);
114+
self.ser_channels.write(writer)?;
115+
Ok(())
116+
}
117+
}
118+
119+
impl Readable for OurPeerStorage {
120+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
121+
let ver = read_ver_prefix!(reader, 1u8);
122+
let ser_channels = <Vec<u8> as Readable>::read(reader)?;
123+
124+
let ps = OurPeerStorage { version: ver, ser_channels };
125+
Ok(ps)
126+
}
127+
}

0 commit comments

Comments
 (0)