pub struct EncryptionService { /* private fields */ }Expand description
Manages encryption keys and provides XChaCha20-Poly1305 encryption/decryption
This implements the security model described in the README:
- Files are encrypted using XChaCha20-Poly1305 for authenticated encryption
- Chunked format enables random-access decryption for efficient range reads
Implementations§
Source§impl EncryptionService
impl EncryptionService
Sourcepub fn new(key_hex: &str) -> Result<Self, EncryptionError>
pub fn new(key_hex: &str) -> Result<Self, EncryptionError>
Create a new encryption service from a hex-encoded key string
Sourcepub fn fingerprint(&self) -> String
pub fn fingerprint(&self) -> String
SHA-256 fingerprint of the key, first 8 bytes hex-encoded (16 hex chars). Short enough to display in UI, long enough to detect wrong keys.
Sourcepub fn new_with_key(key_bytes: &[u8]) -> Self
pub fn new_with_key(key_bytes: &[u8]) -> Self
Create an encryption service with a raw key (for testing)
Sourcepub fn encrypt(&self, plaintext: &[u8]) -> Vec<u8> ⓘ
pub fn encrypt(&self, plaintext: &[u8]) -> Vec<u8> ⓘ
Encrypt data using chunked XChaCha20-Poly1305 format. Returns: [base_nonce: 24 bytes][ciphertext with auth tags] For small data (single chunk), this is equivalent to standard AEAD. For large data, each chunk is independently encrypted for random-access.
Sourcepub fn decrypt(&self, encrypted_data: &[u8]) -> Result<Vec<u8>, EncryptionError>
pub fn decrypt(&self, encrypted_data: &[u8]) -> Result<Vec<u8>, EncryptionError>
Decrypt data in chunked format: [nonce (24 bytes)][ciphertext chunks…]
Sourcepub fn encrypt_chunked(&self, plaintext: &[u8]) -> Vec<u8> ⓘ
pub fn encrypt_chunked(&self, plaintext: &[u8]) -> Vec<u8> ⓘ
Encrypt data using chunked XChaCha20-Poly1305 format.
Returns: [base_nonce: 24 bytes][chunk_0][chunk_1]...
Each chunk is independently encrypted, enabling random-access decryption.
Sourcepub fn decrypt_chunk(
&self,
ciphertext: &[u8],
chunk_index: usize,
) -> Result<Vec<u8>, EncryptionError>
pub fn decrypt_chunk( &self, ciphertext: &[u8], chunk_index: usize, ) -> Result<Vec<u8>, EncryptionError>
Decrypt a specific chunk from chunked encrypted data. Enables random-access decryption without reading preceding chunks.
Sourcepub fn decrypt_chunked(
&self,
ciphertext: &[u8],
) -> Result<Vec<u8>, EncryptionError>
pub fn decrypt_chunked( &self, ciphertext: &[u8], ) -> Result<Vec<u8>, EncryptionError>
Decrypt all chunks from chunked encrypted data.
Sourcepub fn decrypt_range(
&self,
ciphertext: &[u8],
plaintext_start: u64,
plaintext_end: u64,
) -> Result<Vec<u8>, EncryptionError>
pub fn decrypt_range( &self, ciphertext: &[u8], plaintext_start: u64, plaintext_end: u64, ) -> Result<Vec<u8>, EncryptionError>
Decrypt a specific plaintext byte range from encrypted data.
The ciphertext must start with the nonce (first 24 bytes) but may be truncated after the chunks needed for the requested range.
Returns exactly the plaintext bytes from plaintext_start to plaintext_end.
Sourcepub fn decrypt_range_with_offset(
&self,
nonce: &[u8],
encrypted_chunks: &[u8],
first_chunk_index: u64,
plaintext_start: u64,
plaintext_end: u64,
) -> Result<Vec<u8>, EncryptionError>
pub fn decrypt_range_with_offset( &self, nonce: &[u8], encrypted_chunks: &[u8], first_chunk_index: u64, plaintext_start: u64, plaintext_end: u64, ) -> Result<Vec<u8>, EncryptionError>
Decrypt a plaintext byte range using nonce from DB and partial chunk data.
This is the efficient method for encrypted range requests:
nonce: 24-byte nonce stored in DB at import timeencrypted_chunks: Raw encrypted chunk bytes (NO nonce prefix)first_chunk_index: Which chunk index the encrypted_chunks starts atplaintext_start,plaintext_end: Absolute byte positions in original file
Example: To read plaintext bytes 500,000-600,000:
- Calculate needed chunks:
encrypted_chunk_range(500000, 600000)-> chunks 7-9 - Fetch encrypted bytes from cloud at those positions
- Call
decrypt_range_with_offset(nonce, chunks, 7, 500000, 600000)
Sourcepub fn derive_scoped(&self, release_id: &str) -> EncryptionService
pub fn derive_scoped(&self, release_id: &str) -> EncryptionService
Derive a per-release encryption service.
Uses HKDF: master_key + “bae-release-v1:{release_id}” -> 32-byte key. Deterministic: same master + release_id always gives the same key.
Sourcepub fn derive_key(&self, info: &str) -> [u8; 32]
pub fn derive_key(&self, info: &str) -> [u8; 32]
Derive a 32-byte key using HKDF-SHA256 with the given info label.
The derivation is deterministic: same master key + same info string always produces the same derived key.
- Salt:
HMAC-SHA256(master_key, "bae-hkdf-salt-v1") - IKM: master key
- Info: caller-provided label
Trait Implementations§
Source§impl Clone for EncryptionService
impl Clone for EncryptionService
Source§fn clone(&self) -> EncryptionService
fn clone(&self) -> EncryptionService
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for EncryptionService
impl RefUnwindSafe for EncryptionService
impl Send for EncryptionService
impl Sync for EncryptionService
impl Unpin for EncryptionService
impl UnwindSafe for EncryptionService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more