Skip to content

Commit 2fbb5e5

Browse files
committed
fixup: Add OurPeerStorage for serialized Peer Storage backups
1 parent 351df68 commit 2fbb5e5

File tree

1 file changed

+41
-28
lines changed

1 file changed

+41
-28
lines changed

lightning/src/ln/our_peer_storage.rs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//! transmission.
1313
//!
1414
use bitcoin::hashes::sha256::Hash as Sha256;
15-
use bitcoin::hashes::{Hash, HashEngine};
15+
use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine};
1616

1717
use crate::sign::PeerStorageKey;
1818

@@ -45,15 +45,35 @@ pub struct OurPeerStorage {
4545

4646
impl OurPeerStorage {
4747
/// Creates a new [`OurPeerStorage`] with given encrypted_data.
48-
pub fn new(encrypted_data: Vec<u8>) -> Self {
49-
Self { encrypted_data }
48+
pub fn new(encrypted_data: Vec<u8>) -> Result<Self, ()> {
49+
// Length of tag + Length of random_bytes
50+
const MIN_CYPHERTEXT_LEN: usize = 16 + 32;
51+
52+
if encrypted_data.len() < MIN_CYPHERTEXT_LEN {
53+
Err(())
54+
} else {
55+
Ok(Self { encrypted_data })
56+
}
5057
}
5158

5259
/// Get encrypted data stored inside [`OurPeerStorage`].
5360
pub fn into_vec(self) -> Vec<u8> {
5461
self.encrypted_data
5562
}
5663

64+
/// Nonce for encryption and decryption: Hmac(Sha256(key) + random_bytes).
65+
fn derive_nonce(key: &PeerStorageKey, random_bytes: &[u8]) -> [u8; 12] {
66+
let key_hash = Sha256::const_hash(&key.inner);
67+
68+
let mut hmac = HmacEngine::<Sha256>::new(key_hash.as_byte_array());
69+
hmac.input(&random_bytes);
70+
let mut nonce = [0u8; 12];
71+
// First 4 bytes of the nonce should be 0.
72+
nonce[4..].copy_from_slice(&Hmac::from_engine(hmac).to_byte_array()[0..8]);
73+
74+
nonce
75+
}
76+
5777
/// Creates a serialised representation of [`OurPeerStorage`] from the given `ser_channels` data.
5878
///
5979
/// This function takes a `key` (for encryption), `ser_channels` data
@@ -64,17 +84,8 @@ impl OurPeerStorage {
6484
pub fn create_from_data(
6585
key: PeerStorageKey, mut ser_channels: Vec<u8>, random_bytes: [u8; 32],
6686
) -> OurPeerStorage {
67-
let key_hash = Sha256::const_hash(&key.inner);
68-
6987
let plaintext_len = ser_channels.len();
70-
71-
// Compute Sha256(Sha256(key) + random_bytes).
72-
let mut sha = Sha256::engine();
73-
sha.input(&key_hash.to_byte_array());
74-
sha.input(&random_bytes);
75-
76-
let mut nonce = [0u8; 12];
77-
nonce[4..].copy_from_slice(&Sha256::from_engine(sha).to_byte_array()[0..8]);
88+
let nonce = OurPeerStorage::derive_nonce(&key, &random_bytes);
7889

7990
let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
8091
let mut tag = [0; 16];
@@ -90,27 +101,13 @@ impl OurPeerStorage {
90101
/// Decrypt `OurPeerStorage` using the `key`, result is stored inside the `res`.
91102
/// Returns an error if the the `cyphertext` is not correct.
92103
pub fn decrypt_our_peer_storage(mut self, key: PeerStorageKey) -> Result<Vec<u8>, ()> {
93-
let key_hash = Sha256::const_hash(&key.inner);
94-
95-
// Length of tag + Length of random_bytes
96-
const MIN_CYPHERTEXT_LEN: usize = 16 + 32;
97104
let cyphertext_len = self.encrypted_data.len();
98105

99-
// Ensure the cyphertext is at least as large as the MIN_CYPHERTEXT_LEN.
100-
if cyphertext_len < MIN_CYPHERTEXT_LEN {
101-
return Err(());
102-
}
103-
104106
// Ciphertext is of the form: random_bytes(32 bytes) + encrypted_data + tag(16 bytes).
105107
let (data_mut, tag) = self.encrypted_data.split_at_mut(cyphertext_len - 16);
106108
let (random_bytes, encrypted_data) = data_mut.split_at_mut(32);
107109

108-
let mut sha = Sha256::engine();
109-
sha.input(&key_hash.to_byte_array());
110-
sha.input(random_bytes);
111-
112-
let mut nonce = [0u8; 12];
113-
nonce[4..].copy_from_slice(&Sha256::from_engine(sha).to_byte_array()[0..8]);
110+
let nonce = OurPeerStorage::derive_nonce(&key, random_bytes);
114111

115112
let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b"");
116113

@@ -124,3 +121,19 @@ impl OurPeerStorage {
124121
Ok(self.encrypted_data)
125122
}
126123
}
124+
125+
#[cfg(test)]
126+
mod tests {
127+
use crate::ln::our_peer_storage::OurPeerStorage;
128+
use crate::sign::PeerStorageKey;
129+
130+
#[test]
131+
fn test_peer_storage_encryption_decryption() {
132+
let key = PeerStorageKey { inner: [0u8; 32] };
133+
134+
let our_peer_storage =
135+
OurPeerStorage::create_from_data(key.clone(), vec![42u8; 32], [200; 32]);
136+
let decrypted_data = our_peer_storage.decrypt_our_peer_storage(key).unwrap();
137+
assert_eq!(decrypted_data, vec![42u8; 32]);
138+
}
139+
}

0 commit comments

Comments
 (0)