@@ -33,7 +33,7 @@ use std::io;
3333use std:: {
3434 collections:: HashMap ,
3535 path:: { Path , PathBuf } ,
36- sync:: { Arc , OnceLock } ,
36+ sync:: Arc ,
3737} ;
3838
3939#[ cfg( feature = "async-std" ) ]
@@ -81,8 +81,8 @@ pub struct Keyring {
8181 /// Times are stored before reading the file to detect
8282 /// file changes before writing
8383 mtime : Mutex < Option < std:: time:: SystemTime > > ,
84- key : OnceLock < Key > ,
85- secret : Arc < Secret > ,
84+ key : Mutex < Option < Arc < Key > > > ,
85+ secret : Mutex < Arc < Secret > > ,
8686}
8787
8888impl Keyring {
@@ -129,7 +129,7 @@ impl Keyring {
129129 path : path. as_ref ( ) . to_path_buf ( ) ,
130130 mtime : Mutex :: new ( mtime) ,
131131 key : Default :: default ( ) ,
132- secret : Arc :: new ( secret) ,
132+ secret : Mutex :: new ( Arc :: new ( secret) ) ,
133133 } )
134134 }
135135
@@ -147,7 +147,7 @@ impl Keyring {
147147 path : path. as_ref ( ) . to_path_buf ( ) ,
148148 mtime : Default :: default ( ) ,
149149 key : Default :: default ( ) ,
150- secret : Arc :: new ( secret) ,
150+ secret : Mutex :: new ( Arc :: new ( secret) ) ,
151151 } ) ,
152152 Err ( Error :: VersionMismatch ( Some ( version) ) )
153153 if version[ 0 ] == api:: LEGACY_MAJOR_VERSION =>
@@ -169,7 +169,7 @@ impl Keyring {
169169 path : path. as_ref ( ) . to_path_buf ( ) ,
170170 mtime : Default :: default ( ) ,
171171 key : Default :: default ( ) ,
172- secret : Arc :: new ( secret) ,
172+ secret : Mutex :: new ( Arc :: new ( secret) ) ,
173173 } )
174174 }
175175 Err ( err) => Err ( err) ,
@@ -205,7 +205,7 @@ impl Keyring {
205205 path : v1_path,
206206 mtime : Default :: default ( ) ,
207207 key : Default :: default ( ) ,
208- secret : Arc :: new ( secret) ,
208+ secret : Mutex :: new ( Arc :: new ( secret) ) ,
209209 } )
210210 }
211211 }
@@ -229,7 +229,7 @@ impl Keyring {
229229 . items
230230 . iter ( )
231231 . map ( |e| {
232- ( * e) . clone ( ) . decrypt ( key) . map_err ( |err| {
232+ ( * e) . clone ( ) . decrypt ( & key) . map_err ( |err| {
233233 InvalidItemError :: new (
234234 err,
235235 e. hashed_attributes . keys ( ) . map ( |x| x. to_string ( ) ) . collect ( ) ,
@@ -243,22 +243,22 @@ impl Keyring {
243243 pub async fn search_items ( & self , attributes : & impl AsAttributes ) -> Result < Vec < Item > , Error > {
244244 let key = self . derive_key ( ) . await ;
245245 let keyring = self . keyring . read ( ) . await ;
246- keyring. search_items ( attributes, key)
246+ keyring. search_items ( attributes, & key)
247247 }
248248
249249 /// Find the first item matching the attributes.
250250 pub async fn lookup_item ( & self , attributes : & impl AsAttributes ) -> Result < Option < Item > , Error > {
251251 let key = self . derive_key ( ) . await ;
252252 let keyring = self . keyring . read ( ) . await ;
253- keyring. lookup_item ( attributes, key)
253+ keyring. lookup_item ( attributes, & key)
254254 }
255255
256256 /// Delete an item.
257257 pub async fn delete ( & self , attributes : & impl AsAttributes ) -> Result < ( ) , Error > {
258258 {
259259 let key = self . derive_key ( ) . await ;
260260 let mut keyring = self . keyring . write ( ) . await ;
261- keyring. remove_items ( attributes, key) ?;
261+ keyring. remove_items ( attributes, & key) ?;
262262 } ;
263263 self . write ( ) . await
264264 }
@@ -284,10 +284,10 @@ impl Keyring {
284284 let key = self . derive_key ( ) . await ;
285285 let mut keyring = self . keyring . write ( ) . await ;
286286 if replace {
287- keyring. remove_items ( attributes, key) ?;
287+ keyring. remove_items ( attributes, & key) ?;
288288 }
289289 let item = Item :: new ( label, attributes, secret) ;
290- let encrypted_item = item. encrypt ( key) ?;
290+ let encrypted_item = item. encrypt ( & key) ?;
291291 keyring. items . push ( encrypted_item) ;
292292 item
293293 } ;
@@ -308,7 +308,7 @@ impl Keyring {
308308 let mut keyring = self . keyring . write ( ) . await ;
309309
310310 if let Some ( item_store) = keyring. items . get_mut ( index) {
311- * item_store = item. encrypt ( key) ?;
311+ * item_store = item. encrypt ( & key) ?;
312312 } else {
313313 return Err ( Error :: InvalidItemIndex ( index) ) ;
314314 }
@@ -340,10 +340,10 @@ impl Keyring {
340340 let mut keyring = self . keyring . write ( ) . await ;
341341 for ( label, attributes, secret, replace) in items {
342342 if replace {
343- keyring. remove_items ( & attributes, key) ?;
343+ keyring. remove_items ( & attributes, & key) ?;
344344 }
345345 let item = Item :: new ( label, & attributes, & * secret) ;
346- let encrypted_item = item. encrypt ( key) ?;
346+ let encrypted_item = item. encrypt ( & key) ?;
347347 keyring. items . push ( encrypted_item) ;
348348 }
349349
@@ -374,12 +374,52 @@ impl Keyring {
374374 }
375375
376376 /// Return key, derive and store it first if not initialized
377- async fn derive_key ( & self ) -> & Key {
378- if self . key . get ( ) . is_none ( ) {
377+ async fn derive_key ( & self ) -> Arc < Key > {
378+ if self . key . lock ( ) . await . is_none ( ) {
379379 let key = self . keyring . read ( ) . await . derive_key ( & self . secret ) ;
380- self . key . set ( key ) . unwrap ( ) ;
380+ * self . key . lock ( ) . await = Some ( Arc :: new ( key ) ) ;
381381 }
382- self . key . get ( ) . unwrap ( )
382+
383+ Arc :: clone ( self . key . lock ( ) . await . as_ref ( ) . unwrap ( ) )
384+ }
385+
386+ /// Change keyring secret
387+ ///
388+ /// # Arguments
389+ ///
390+ /// * `secret` - The new secret to store.
391+ pub async fn change_secret ( & self , secret : Secret ) -> Result < ( ) , Error > {
392+ #[ cfg( feature = "tracing" ) ]
393+ tracing:: debug!( "Changing keyring secret and key" ) ;
394+
395+ let keyring = self . keyring . read ( ) . await ;
396+ let key = self . derive_key ( ) . await ;
397+
398+ let mut items = Vec :: with_capacity ( keyring. items . len ( ) ) ;
399+ for item in & keyring. items {
400+ items. push ( item. clone ( ) . decrypt ( & key) ?) ;
401+ }
402+ drop ( keyring) ;
403+
404+ let mut secret_lock = self . secret . lock ( ) . await ;
405+ * secret_lock = Arc :: new ( secret) ;
406+ drop ( secret_lock) ;
407+
408+ let mut key_lock = self . key . lock ( ) . await ;
409+ // Unset the old key
410+ * key_lock = None ;
411+ drop ( key_lock) ;
412+ let key = self . derive_key ( ) . await ;
413+
414+ let mut keyring = self . keyring . write ( ) . await ;
415+
416+ for item in items {
417+ let encrypted_item = item. encrypt ( & key) ?;
418+ keyring. items . push ( encrypted_item) ;
419+ }
420+ drop ( keyring) ;
421+
422+ self . write ( ) . await
383423 }
384424}
385425
@@ -609,4 +649,30 @@ mod tests {
609649
610650 Ok ( ( ) )
611651 }
652+
653+ #[ tokio:: test]
654+ async fn change_secret ( ) -> Result < ( ) , Error > {
655+ let path = PathBuf :: from ( "../../tests/test_rekeying.keyring" ) ;
656+
657+ let keyring = Keyring :: load ( & path, strong_key ( ) ) . await ?;
658+ let attributes = HashMap :: from ( [ ( "attr" , "value" ) ] ) ;
659+ let item_before = keyring
660+ . create_item ( "test" , & attributes, "password" , false )
661+ . await ?;
662+
663+ let new_secret = Secret :: from ( b"password" . to_vec ( ) ) ;
664+ keyring. change_secret ( new_secret) . await ?;
665+
666+ let new_secret = Secret :: from ( b"password" . to_vec ( ) ) ;
667+ let keyring = Keyring :: load ( & path, new_secret) . await ?;
668+ let item_now = keyring. lookup_item ( & attributes) . await ?. unwrap ( ) ;
669+
670+ assert_eq ! ( item_before. label( ) , item_now. label( ) ) ;
671+ assert_eq ! ( item_before. secret( ) , item_now. secret( ) ) ;
672+ assert_eq ! ( item_before. attributes( ) , item_now. attributes( ) ) ;
673+
674+ fs:: remove_file ( path) . await ?;
675+
676+ Ok ( ( ) )
677+ }
612678}
0 commit comments