7
7
// You may not use this file except in accordance with one or both of these
8
8
// licenses.
9
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.
10
+ //! `OurPeerStorage` enables storage of encrypted serialized channel data.
11
+ //! It provides encryption and decryption of data to maintain data integrity and
12
+ //! security during transmission.
13
13
//!
14
+
14
15
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
15
16
use bitcoin:: hashes:: { Hash , HashEngine , Hmac , HmacEngine } ;
16
17
@@ -19,14 +20,15 @@ use crate::sign::PeerStorageKey;
19
20
use crate :: crypto:: chacha20poly1305rfc:: ChaCha20Poly1305RFC ;
20
21
use crate :: prelude:: * ;
21
22
22
- /// [`OurPeerStorage`] is used to store channel information that allows for the creation of a
23
+ /// [`OurPeerStorage`] is used to store encrypted channel information that allows for the creation of a
23
24
/// `peer_storage` backup.
24
25
///
25
26
/// This structure is designed to serialize channel data for backup and supports encryption
26
- /// and decryption using `ChaCha20Poly1305RFC` to ensure data integrity and security during exchange or storage .
27
+ /// and decryption using `ChaCha20Poly1305RFC` for transmission .
27
28
///
28
29
/// # Key Methods
29
- /// - [`OurPeerStorage::create_from_data`]: Returns an encrypted [`OurPeerStorage`] instance created from the provided data.
30
+ /// - [`OurPeerStorage::new`]: Returns [`OurPeerStorage`] with the given encrypted_data.
31
+ /// - [`OurPeerStorage::create_from_data`]: Returns [`OurPeerStorage`] created from encrypting the provided data.
30
32
/// - [`OurPeerStorage::decrypt_our_peer_storage`]: Decrypts the [`OurPeerStorage::encrypted_data`] using the key and returns decrypted data.
31
33
///
32
34
/// ## Example
@@ -45,6 +47,8 @@ pub struct OurPeerStorage {
45
47
46
48
impl OurPeerStorage {
47
49
/// Creates a new [`OurPeerStorage`] with given encrypted_data.
50
+ /// Returns an error if the `encrypted_data` is less than the
51
+ /// appropriate length.
48
52
pub fn new ( encrypted_data : Vec < u8 > ) -> Result < Self , ( ) > {
49
53
// Length of tag + Length of random_bytes
50
54
const MIN_CYPHERTEXT_LEN : usize = 16 + 32 ;
@@ -61,39 +65,26 @@ impl OurPeerStorage {
61
65
self . encrypted_data
62
66
}
63
67
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
-
77
- /// Creates a serialised representation of [`OurPeerStorage`] from the given `ser_channels` data.
68
+ /// Returns [`OurPeerStorage`] with encrypted `ser_channels`.
78
69
///
79
70
/// This function takes a `key` (for encryption), `ser_channels` data
80
- /// (serialised channel information) and random_bytes (to derive nonce for encryption) and returns a serialised
81
- /// [`OurPeerStorage`] as a `Vec<u8>` .
71
+ /// (serialised channel information) and random_bytes (to derive nonce for encryption) and returns a
72
+ /// [`OurPeerStorage`] with encrypted data inside .
82
73
///
83
74
/// The resulting serialised data is intended to be directly used for transmission to the peers.
84
75
pub fn create_from_data (
85
76
key : PeerStorageKey , mut ser_channels : Vec < u8 > , random_bytes : [ u8 ; 32 ] ,
86
77
) -> OurPeerStorage {
87
78
let plaintext_len = ser_channels. len ( ) ;
88
- let nonce = OurPeerStorage :: derive_nonce ( & key, & random_bytes) ;
79
+ let nonce = derive_nonce ( & key, & random_bytes) ;
89
80
90
81
let mut chacha = ChaCha20Poly1305RFC :: new ( & key. inner , & nonce, b"" ) ;
91
82
let mut tag = [ 0 ; 16 ] ;
92
83
chacha. encrypt_full_message_in_place ( & mut ser_channels[ 0 ..plaintext_len] , & mut tag) ;
93
84
94
85
ser_channels. extend_from_slice ( & tag) ;
95
86
96
- // Append `random_bytes` in front of the encrypted_blob.
87
+ // Prepend `random_bytes` in front of the encrypted_blob.
97
88
ser_channels. splice ( 0 ..0 , random_bytes) ;
98
89
Self { encrypted_data : ser_channels }
99
90
}
@@ -107,7 +98,7 @@ impl OurPeerStorage {
107
98
let ( data_mut, tag) = self . encrypted_data . split_at_mut ( cyphertext_len - 16 ) ;
108
99
let ( random_bytes, encrypted_data) = data_mut. split_at_mut ( 32 ) ;
109
100
110
- let nonce = OurPeerStorage :: derive_nonce ( & key, random_bytes) ;
101
+ let nonce = derive_nonce ( & key, random_bytes) ;
111
102
112
103
let mut chacha = ChaCha20Poly1305RFC :: new ( & key. inner , & nonce, b"" ) ;
113
104
@@ -122,18 +113,54 @@ impl OurPeerStorage {
122
113
}
123
114
}
124
115
116
+ /// Nonce for encryption and decryption: Hmac(Sha256(key) + random_bytes).
117
+ fn derive_nonce ( key : & PeerStorageKey , random_bytes : & [ u8 ] ) -> [ u8 ; 12 ] {
118
+ let key_hash = Sha256 :: const_hash ( & key. inner ) ;
119
+
120
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( key_hash. as_byte_array ( ) ) ;
121
+ hmac. input ( & random_bytes) ;
122
+ let mut nonce = [ 0u8 ; 12 ] ;
123
+ // First 4 bytes of the nonce should be 0.
124
+ nonce[ 4 ..] . copy_from_slice ( & Hmac :: from_engine ( hmac) . to_byte_array ( ) [ 0 ..8 ] ) ;
125
+
126
+ nonce
127
+ }
128
+
125
129
#[ cfg( test) ]
126
130
mod tests {
127
- use crate :: ln:: our_peer_storage:: OurPeerStorage ;
131
+ use crate :: ln:: our_peer_storage:: { derive_nonce , OurPeerStorage } ;
128
132
use crate :: sign:: PeerStorageKey ;
129
133
130
134
#[ test]
131
135
fn test_peer_storage_encryption_decryption ( ) {
132
- let key = PeerStorageKey { inner : [ 0u8 ; 32 ] } ;
136
+ let key1 = PeerStorageKey { inner : [ 0u8 ; 32 ] } ;
137
+ let key2 = PeerStorageKey { inner : [ 1u8 ; 32 ] } ;
138
+ let random_bytes1 = [ 200 ; 32 ] ;
139
+ let random_bytes2 = [ 201 ; 32 ] ;
133
140
141
+ // Happy Path
134
142
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 ( ) ;
143
+ OurPeerStorage :: create_from_data ( key1 . clone ( ) , vec ! [ 42u8 ; 32 ] , random_bytes1 ) ;
144
+ let decrypted_data = our_peer_storage. decrypt_our_peer_storage ( key1 . clone ( ) ) . unwrap ( ) ;
137
145
assert_eq ! ( decrypted_data, vec![ 42u8 ; 32 ] ) ;
146
+
147
+ // Changing Key
148
+ let our_peer_storage_wrong_key =
149
+ OurPeerStorage :: create_from_data ( key1. clone ( ) , vec ! [ 42u8 ; 32 ] , random_bytes1) ;
150
+ let decrypted_data_wrong_key = our_peer_storage_wrong_key. decrypt_our_peer_storage ( key2) ;
151
+ assert ! ( decrypted_data_wrong_key. is_err( ) ) ;
152
+
153
+ // Nonce derivation happy path
154
+ let nonce = derive_nonce ( & key1, & random_bytes1) ;
155
+ let nonce_happy_path = derive_nonce ( & key1, & random_bytes1) ;
156
+ assert_eq ! ( nonce, nonce_happy_path) ;
157
+
158
+ // Nonce derivation with different `random_bytes` & `key`
159
+ let nonce_diff_random_bytes = derive_nonce ( & key1, & random_bytes2) ;
160
+ let nonce_diff_key = derive_nonce ( & key2, & random_bytes1) ;
161
+ let nonce_diff_key_random_bytes = derive_nonce ( & key2, & random_bytes2) ;
162
+ assert_ne ! ( nonce, nonce_diff_random_bytes) ;
163
+ assert_ne ! ( nonce, nonce_diff_key) ;
164
+ assert_ne ! ( nonce, nonce_diff_key_random_bytes) ;
138
165
}
139
166
}
0 commit comments