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

Function write_encrypted_segment

nodedb/src/storage/segment.rs:147–184  ·  view source on GitHub ↗

Write a segment file with optional encryption. Layout (encrypted): `[preamble(16B plaintext)] [ciphertext(data_len + 16B auth_tag)] [footer(58B plaintext)]` Layout (unencrypted): `[data] [footer(58B plaintext)]` The preamble contains a freshly-generated random epoch. The nonce used for AES-256-GCM is `(preamble.epoch, min_lsn)`. The preamble bytes and a fixed AAD tag are included as Additional

(
    path: &Path,
    data: &[u8],
    footer: &SegmentFooter,
    key: Option<&nodedb_wal::crypto::WalEncryptionKey>,
)

Source from the content-addressed store, hash-verified

145/// Two segments that share `min_lsn` (e.g. LSN=0 at bootstrap) will have
146/// different epochs and therefore non-colliding nonces.
147pub fn write_encrypted_segment(
148 path: &Path,
149 data: &[u8],
150 footer: &SegmentFooter,
151 key: Option<&nodedb_wal::crypto::WalEncryptionKey>,
152) -> crate::Result<()> {
153 let mut file = std::fs::File::create(path)?;
154
155 if let Some(key) = key {
156 // Create a fresh-epoch key for this segment. Each segment write gets
157 // its own epoch so even two segments with the same min_lsn (e.g.
158 // both starting at LSN 0 at bootstrap) have non-colliding nonces.
159 // `with_fresh_epoch` re-uses the same AES key bytes but generates a
160 // new random epoch — the nonce for encryption will use this epoch,
161 // and we record the same epoch in the preamble.
162 let fresh_key = key.with_fresh_epoch().map_err(crate::Error::Wal)?;
163 let epoch = *fresh_key.epoch();
164 let preamble = SegmentPreamble::new_seg(epoch);
165 let preamble_bytes = preamble.to_bytes();
166
167 // AAD = preamble_bytes (binds ciphertext to this segment's preamble).
168 let ciphertext = fresh_key
169 .encrypt_aad(footer.min_lsn.as_u64(), &preamble_bytes, data)
170 .map_err(|e| crate::Error::Storage {
171 engine: "segment".into(),
172 detail: format!("segment encryption failed: {e}"),
173 })?;
174
175 file.write_all(&preamble_bytes)?;
176 file.write_all(&ciphertext)?;
177 } else {
178 file.write_all(data)?;
179 }
180
181 file.write_all(&footer.to_bytes())?;
182 file.flush()?;
183 Ok(())
184}
185
186/// Encrypt segment data into a self-describing byte envelope (no file I/O).
187///

Calls 7

with_fresh_epochMethod · 0.80
encrypt_aadMethod · 0.80
createFunction · 0.50
epochMethod · 0.45
to_bytesMethod · 0.45
as_u64Method · 0.45
flushMethod · 0.45