12
12
//! transmission.
13
13
//!
14
14
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
15
- use bitcoin:: hashes:: { Hash , HashEngine } ;
15
+ use bitcoin:: hashes:: { Hash , HashEngine , Hmac , HmacEngine } ;
16
16
17
17
use crate :: sign:: PeerStorageKey ;
18
18
@@ -45,15 +45,35 @@ pub struct OurPeerStorage {
45
45
46
46
impl OurPeerStorage {
47
47
/// 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
+ }
50
57
}
51
58
52
59
/// Get encrypted data stored inside [`OurPeerStorage`].
53
60
pub fn into_vec ( self ) -> Vec < u8 > {
54
61
self . encrypted_data
55
62
}
56
63
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
+
57
77
/// Creates a serialised representation of [`OurPeerStorage`] from the given `ser_channels` data.
58
78
///
59
79
/// This function takes a `key` (for encryption), `ser_channels` data
@@ -64,17 +84,8 @@ impl OurPeerStorage {
64
84
pub fn create_from_data (
65
85
key : PeerStorageKey , mut ser_channels : Vec < u8 > , random_bytes : [ u8 ; 32 ] ,
66
86
) -> OurPeerStorage {
67
- let key_hash = Sha256 :: const_hash ( & key. inner ) ;
68
-
69
87
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) ;
78
89
79
90
let mut chacha = ChaCha20Poly1305RFC :: new ( & key. inner , & nonce, b"" ) ;
80
91
let mut tag = [ 0 ; 16 ] ;
@@ -90,27 +101,13 @@ impl OurPeerStorage {
90
101
/// Decrypt `OurPeerStorage` using the `key`, result is stored inside the `res`.
91
102
/// Returns an error if the the `cyphertext` is not correct.
92
103
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 ;
97
104
let cyphertext_len = self . encrypted_data . len ( ) ;
98
105
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
-
104
106
// Ciphertext is of the form: random_bytes(32 bytes) + encrypted_data + tag(16 bytes).
105
107
let ( data_mut, tag) = self . encrypted_data . split_at_mut ( cyphertext_len - 16 ) ;
106
108
let ( random_bytes, encrypted_data) = data_mut. split_at_mut ( 32 ) ;
107
109
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) ;
114
111
115
112
let mut chacha = ChaCha20Poly1305RFC :: new ( & key. inner , & nonce, b"" ) ;
116
113
@@ -124,3 +121,19 @@ impl OurPeerStorage {
124
121
Ok ( self . encrypted_data )
125
122
}
126
123
}
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