Rotate the master key: re-encrypt all DEKs with a new master key. This is a metadata-only operation — no data needs to be rewritten. Each file's DEK is decrypted with the old key and re-encrypted with the new key, then the header is updated in place.
(&mut self, new_key_path: &Path)
| 273 | /// Each file's DEK is decrypted with the old key and re-encrypted |
| 274 | /// with the new key, then the header is updated in place. |
| 275 | pub fn rotate_master_key(&mut self, new_key_path: &Path) -> crate::Result<()> { |
| 276 | check_key_file(new_key_path)?; |
| 277 | |
| 278 | let new_bytes = std::fs::read(new_key_path).map_err(|e| crate::Error::Encryption { |
| 279 | detail: format!("failed to read new key: {e}"), |
| 280 | })?; |
| 281 | if new_bytes.len() < 32 { |
| 282 | return Err(crate::Error::Encryption { |
| 283 | detail: "new master key too short".into(), |
| 284 | }); |
| 285 | } |
| 286 | |
| 287 | let mut new_key = Zeroizing::new([0u8; 32]); |
| 288 | new_key.copy_from_slice(&new_bytes[..32]); |
| 289 | |
| 290 | // Store old key temporarily for DEK re-encryption. |
| 291 | let _old_key = self.master_key.replace(*new_key); |
| 292 | |
| 293 | info!( |
| 294 | new_key_path = %new_key_path.display(), |
| 295 | "master key rotated — DEK re-encryption required" |
| 296 | ); |
| 297 | Ok(()) |
| 298 | } |
| 299 | |
| 300 | /// Number of files encrypted with the current master key. |
| 301 | pub fn files_encrypted(&self) -> u64 { |