feat(carrier): implement carrier format V2 paged manifest and secondary index
This commit is contained in:
+66
-12
@@ -713,8 +713,8 @@ impl Database {
|
||||
)?;
|
||||
let c_id = conn.last_insert_rowid();
|
||||
|
||||
// Berechne Blockanzahl (min. 2 Blöcke: Block 0 für Manifest, Block 1+ für Nutzdaten)
|
||||
let total_blocks = c_size.div_ceil(CHUNK_SIZE as u64).max(2) as u32;
|
||||
// Berechne Blockanzahl (min. 3 Blöcke: Block 0/1 für Superblock, Block 2 für Inode-Seite)
|
||||
let total_blocks = c_size.div_ceil(CHUNK_SIZE as u64).max(3) as u32;
|
||||
|
||||
// Slot 1 (Hidden Vault) einfügen
|
||||
let params_json_1 = serde_json::to_string(h_params)?;
|
||||
@@ -732,13 +732,67 @@ impl Database {
|
||||
],
|
||||
)?;
|
||||
|
||||
// Initialisiere CarrierManifest für redundante Blöcke 0 und 1 (C-02)
|
||||
// Initialisiere Carrier-Format V2 (Superblock auf Block 0/1, Inode-Seite auf Block 2)
|
||||
let manifest = crate::carrier::CarrierManifest::new(total_blocks);
|
||||
let manifest_bytes = serde_json::to_vec(&manifest)?;
|
||||
|
||||
// 1. Block 0 schreiben (Primärkopie, Gen 0)
|
||||
// 1. Block 2 schreiben: Erste Inode-Tabellenseite mit Wurzelverzeichnis '/'
|
||||
let root_page = crate::carrier::CarrierInodePage {
|
||||
magic: *crate::carrier::CARRIER_PAGE_MAGIC,
|
||||
entries: manifest.inodes.values().cloned().collect(),
|
||||
};
|
||||
let root_page_bytes = serde_json::to_vec(&root_page)?;
|
||||
|
||||
let (inner_ct_2, inner_nonce_2, inner_tag_2) =
|
||||
crate::crypto::encrypt_chunk(dek_1, c_id, 2, &root_page_bytes, FORMAT_VERSION, 0)?;
|
||||
let inner_ct_len_2 = inner_ct_2.len() as u32;
|
||||
|
||||
let mut outer_plaintext_2 = vec![0u8; CHUNK_SIZE];
|
||||
OsRng.fill_bytes(&mut outer_plaintext_2);
|
||||
|
||||
outer_plaintext_2[0..12].copy_from_slice(&inner_nonce_2);
|
||||
outer_plaintext_2[12..28].copy_from_slice(&inner_tag_2);
|
||||
outer_plaintext_2[28..32].copy_from_slice(&inner_ct_len_2.to_le_bytes());
|
||||
let ct_end_2 = 32 + inner_ct_2.len();
|
||||
if ct_end_2 > CHUNK_SIZE {
|
||||
bail!("Inode-Page-Payload zu groß für Block 2");
|
||||
}
|
||||
outer_plaintext_2[32..ct_end_2].copy_from_slice(&inner_ct_2);
|
||||
|
||||
let (outer_ct_2, outer_nonce_2, outer_tag_2) = crate::crypto::encrypt_chunk(
|
||||
dek_0,
|
||||
c_id,
|
||||
2,
|
||||
&outer_plaintext_2,
|
||||
FORMAT_VERSION,
|
||||
0,
|
||||
)?;
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO chunks (node_id, chunk_index, generation, nonce, tag, ciphertext)
|
||||
VALUES (?1, 2, 0, ?2, ?3, ?4)",
|
||||
params![
|
||||
c_id,
|
||||
outer_nonce_2.as_slice(),
|
||||
outer_tag_2.as_slice(),
|
||||
outer_ct_2
|
||||
],
|
||||
)?;
|
||||
|
||||
// 2. Superblock (Block 0 & 1, redundante Zweitkopie C-02, Format V2)
|
||||
let superblock = crate::carrier::CarrierSuperblock {
|
||||
magic: *crate::carrier::CARRIER_MAGIC,
|
||||
version: crate::carrier::CARRIER_VERSION_V2,
|
||||
manifest_generation: 0,
|
||||
total_blocks,
|
||||
free_blocks: manifest.free_blocks.clone(),
|
||||
next_inode_id: manifest.next_inode_id,
|
||||
page_block_indices: vec![2],
|
||||
};
|
||||
let sb_bytes = serde_json::to_vec(&superblock)?;
|
||||
|
||||
// Block 0 schreiben (Primärkopie)
|
||||
let (inner_ct_0, inner_nonce_0, inner_tag_0) =
|
||||
crate::crypto::encrypt_chunk(dek_1, c_id, 0, &manifest_bytes, FORMAT_VERSION, 0)?;
|
||||
crate::crypto::encrypt_chunk(dek_1, c_id, 0, &sb_bytes, FORMAT_VERSION, 0)?;
|
||||
let inner_ct_len_0 = inner_ct_0.len() as u32;
|
||||
|
||||
let mut outer_plaintext_0 = vec![0u8; CHUNK_SIZE];
|
||||
@@ -749,7 +803,7 @@ impl Database {
|
||||
outer_plaintext_0[28..32].copy_from_slice(&inner_ct_len_0.to_le_bytes());
|
||||
let ct_end_0 = 32 + inner_ct_0.len();
|
||||
if ct_end_0 > CHUNK_SIZE {
|
||||
bail!("Manifest-Payload zu groß für Block 0");
|
||||
bail!("Superblock-Payload zu groß für Block 0");
|
||||
}
|
||||
outer_plaintext_0[32..ct_end_0].copy_from_slice(&inner_ct_0);
|
||||
|
||||
@@ -773,9 +827,9 @@ impl Database {
|
||||
],
|
||||
)?;
|
||||
|
||||
// 2. Block 1 schreiben (Redundante Zweitkopie, Gen 0, C-02)
|
||||
// Block 1 schreiben (Redundante Zweitkopie, C-02)
|
||||
let (inner_ct_1, inner_nonce_1, inner_tag_1) =
|
||||
crate::crypto::encrypt_chunk(dek_1, c_id, 1, &manifest_bytes, FORMAT_VERSION, 0)?;
|
||||
crate::crypto::encrypt_chunk(dek_1, c_id, 1, &sb_bytes, FORMAT_VERSION, 0)?;
|
||||
let inner_ct_len_1 = inner_ct_1.len() as u32;
|
||||
|
||||
let mut outer_plaintext_1 = vec![0u8; CHUNK_SIZE];
|
||||
@@ -786,7 +840,7 @@ impl Database {
|
||||
outer_plaintext_1[28..32].copy_from_slice(&inner_ct_len_1.to_le_bytes());
|
||||
let ct_end_1 = 32 + inner_ct_1.len();
|
||||
if ct_end_1 > CHUNK_SIZE {
|
||||
bail!("Manifest-Payload zu groß für Block 1");
|
||||
bail!("Superblock-Payload zu groß für Block 1");
|
||||
}
|
||||
outer_plaintext_1[32..ct_end_1].copy_from_slice(&inner_ct_1);
|
||||
|
||||
@@ -810,7 +864,7 @@ impl Database {
|
||||
],
|
||||
)?;
|
||||
|
||||
// Blöcke 2..total_blocks-1 mit DEK_0 vorallokieren (C-02)
|
||||
// 3. Blöcke 3..total_blocks-1 mit DEK_0 vorallokieren
|
||||
let mut chunk_stmt = conn.prepare(
|
||||
"INSERT INTO chunks (node_id, chunk_index, generation, nonce, tag, ciphertext)
|
||||
VALUES (?1, ?2, 0, ?3, ?4, ?5)",
|
||||
@@ -820,7 +874,7 @@ impl Database {
|
||||
OsRng.fill_bytes(&mut dummy_noise);
|
||||
|
||||
conn.execute_batch("BEGIN TRANSACTION;")?;
|
||||
for b in 2..total_blocks {
|
||||
for b in 3..total_blocks {
|
||||
let (ct, nonce, tag) =
|
||||
crate::crypto::encrypt_chunk(dek_0, c_id, b, &dummy_noise, FORMAT_VERSION, 0)?;
|
||||
chunk_stmt.execute(params![c_id, b, nonce.as_slice(), tag.as_slice(), ct,])?;
|
||||
|
||||
Reference in New Issue
Block a user