MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / read_encrypted_segment

Function read_encrypted_segment

nodedb/src/storage/segment.rs:271–326  ·  view source on GitHub ↗

Read and decrypt a segment file's data portion. For encrypted segments, reads the 16-byte `SEGP` preamble at the start of the file to recover the epoch, then uses it for nonce reconstruction. Returns the plaintext data (footer is stripped and validated separately).

(
    path: &Path,
    key: Option<&nodedb_wal::crypto::WalEncryptionKey>,
)

Source from the content-addressed store, hash-verified

269/// the file to recover the epoch, then uses it for nonce reconstruction.
270/// Returns the plaintext data (footer is stripped and validated separately).
271pub fn read_encrypted_segment(
272 path: &Path,
273 key: Option<&nodedb_wal::crypto::WalEncryptionKey>,
274) -> crate::Result<Vec<u8>> {
275 let raw = std::fs::read(path)?;
276
277 if let Some(key) = key {
278 // Encrypted layout: [preamble(16)] [ciphertext] [footer(58)]
279 let min_len = PREAMBLE_SIZE + nodedb_wal::crypto::AUTH_TAG_SIZE + FOOTER_SIZE;
280 if raw.len() < min_len {
281 return Err(crate::Error::SegmentCorrupted {
282 detail: "encrypted segment file too small".into(),
283 });
284 }
285
286 // Read and validate the preamble.
287 let preamble_bytes: [u8; PREAMBLE_SIZE] = raw[..PREAMBLE_SIZE]
288 .try_into()
289 .expect("slice is PREAMBLE_SIZE bytes");
290 let preamble =
291 SegmentPreamble::from_bytes(&preamble_bytes, &SEG_PREAMBLE_MAGIC).map_err(|e| {
292 crate::Error::SegmentCorrupted {
293 detail: format!("invalid segment preamble: {e}"),
294 }
295 })?;
296
297 // Footer is at the end.
298 let footer_bytes: [u8; FOOTER_SIZE] = raw[raw.len() - FOOTER_SIZE..]
299 .try_into()
300 .expect("slice is FOOTER_SIZE bytes");
301 let footer = SegmentFooter::from_bytes(&footer_bytes)?;
302
303 // Ciphertext is between preamble and footer.
304 let ciphertext = &raw[PREAMBLE_SIZE..raw.len() - FOOTER_SIZE];
305
306 // Decrypt: epoch from preamble, nonce input is min_lsn.
307 key.decrypt_aad(
308 preamble.epoch(),
309 footer.min_lsn.as_u64(),
310 &preamble_bytes,
311 ciphertext,
312 )
313 .map_err(|e| crate::Error::Storage {
314 engine: "segment".into(),
315 detail: format!("segment decryption failed: {e}"),
316 })
317 } else {
318 // Unencrypted layout: [data] [footer(58)]
319 if raw.len() < FOOTER_SIZE {
320 return Err(crate::Error::SegmentCorrupted {
321 detail: "file too small".into(),
322 });
323 }
324 Ok(raw[..raw.len() - FOOTER_SIZE].to_vec())
325 }
326}
327
328#[cfg(test)]

Calls 7

decrypt_aadMethod · 0.80
readFunction · 0.50
lenMethod · 0.45
expectMethod · 0.45
epochMethod · 0.45
as_u64Method · 0.45
to_vecMethod · 0.45