1212//! transmission.
1313//!
1414use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
15- use bitcoin:: hashes:: { Hash , HashEngine } ;
15+ use bitcoin:: hashes:: { Hash , HashEngine , Hmac , HmacEngine } ;
1616
1717use crate :: sign:: PeerStorageKey ;
1818
@@ -45,15 +45,35 @@ pub struct OurPeerStorage {
4545
4646impl 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