mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-03 02:38:12 +00:00
feat(ecstore): closed-form range seek for single-part v2 encrypted objects (#6601)
Single-part encrypted objects in the legacy format could not serve range reads without decrypting from byte 0: v1 frames are emitted per upstream read, so no closed-form plaintext-to-ciphertext mapping exists. The v2 layout fixed the frame length (8218 ciphertext bytes per 8 KiB plaintext frame), making the mapping closed-form. Consume it: - Single-part PUTs that encrypt locally under the v2 write switch stamp the frame-layout marker, valued with the object's data_dir token - ciphertext passthrough, data movement and copies mint a new data_dir or strip the marker, so a re-homed marker disqualifies itself. - The encrypted read plan seeks marked, uncompressed single-part objects to frame_index * 8218 and decrypts from that frame: the frame index rides the plan's sequence-number slot into DecryptReader::new_at_block, whose nonce and AAD bind absolute indices. New metric path label frame_seek. - A lying marker fails closed: v2 authentication rejects bytes at a fake frame boundary; plaintext is never served from the wrong offset. Compressed objects and multipart sub-part seeks keep the conservative paths (follow-up work); reading needs no switch - seekability follows the marker.
This commit is contained in:
@@ -180,6 +180,12 @@ where
|
||||
#[cfg(feature = "rio-v2")]
|
||||
{
|
||||
match backend {
|
||||
// The legacy family includes v2 fixed-frame objects, whose plans
|
||||
// seek by frame; honor the starting index here too so a rio-v2
|
||||
// build can range-read objects a default-build node wrote.
|
||||
ReadEncryptionBackend::Legacy if sequence_number > 0 => {
|
||||
Box::new(rustfs_rio::DecryptReader::new_at_block(reader, key, base_nonce, sequence_number as usize))
|
||||
}
|
||||
ReadEncryptionBackend::Legacy => Box::new(rustfs_rio::DecryptReader::new(reader, key, base_nonce)),
|
||||
ReadEncryptionBackend::V2 => {
|
||||
Box::new(rustfs_rio_v2::DecryptReader::new_with_sequence(reader, key, base_nonce, sequence_number))
|
||||
@@ -189,8 +195,14 @@ where
|
||||
|
||||
#[cfg(not(feature = "rio-v2"))]
|
||||
{
|
||||
let _ = (backend, sequence_number);
|
||||
Box::new(rustfs_rio::DecryptReader::new(reader, key, base_nonce))
|
||||
let _ = backend;
|
||||
if sequence_number > 0 {
|
||||
// Single-part v2 frame seek: the plan positioned the storage read
|
||||
// at frame `sequence_number`; nonce and AAD bind absolute indices.
|
||||
Box::new(rustfs_rio::DecryptReader::new_at_block(reader, key, base_nonce, sequence_number as usize))
|
||||
} else {
|
||||
Box::new(rustfs_rio::DecryptReader::new(reader, key, base_nonce))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user