test(crypto): M-05 — verify schema equality between standard and hidden vault containers
This commit is contained in:
@@ -774,3 +774,155 @@ async fn test_v01_carrier_fs_copy_delegation_and_functionality() {
|
||||
let _ = std::fs::remove_file(&path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_m05_deniability_schema_equality_standard_vs_hidden() {
|
||||
let path_std = temp_db_path("schema_std");
|
||||
let path_hidden = temp_db_path("schema_hidden");
|
||||
|
||||
let kdf_params = KdfParams {
|
||||
memory_cost: MIN_MEMORY_COST_KIB,
|
||||
time_cost: MIN_TIME_COST,
|
||||
parallelism: 1,
|
||||
};
|
||||
|
||||
let salt_std = generate_salt();
|
||||
let kek_std = derive_kek("StandardPass123!", &salt_std, &kdf_params).unwrap();
|
||||
let dek_std = generate_dek();
|
||||
let (wrapped_std, nonce_std, tag_std) = wrap_slot0_payload(&kek_std, &dek_std, 0).unwrap();
|
||||
|
||||
let db_std = Database::open(&path_std).expect("Open std db");
|
||||
db_std
|
||||
.init_schema(
|
||||
&salt_std,
|
||||
&kdf_params,
|
||||
&wrapped_std,
|
||||
&nonce_std,
|
||||
&tag_std,
|
||||
)
|
||||
.expect("Init std schema");
|
||||
db_std.checkpoint().unwrap();
|
||||
|
||||
let salt_0 = generate_salt();
|
||||
let kek_0 = derive_kek("DecoyPass123!", &salt_0, &kdf_params).unwrap();
|
||||
let dek_0 = generate_dek();
|
||||
|
||||
let salt_1 = generate_salt();
|
||||
let kek_1 = derive_kek("HiddenPass123!", &salt_1, &kdf_params).unwrap();
|
||||
let dek_1 = generate_dek();
|
||||
|
||||
let carrier_node_id = 3i64;
|
||||
let (wrapped_0, nonce_0, tag_0) = wrap_slot0_payload(&kek_0, &dek_0, carrier_node_id).unwrap();
|
||||
let (wrapped_1, nonce_1, tag_1) =
|
||||
wrap_slot1_payload(&kek_1, &dek_1, &dek_0, carrier_node_id).unwrap();
|
||||
|
||||
let db_hidden = Database::open(&path_hidden).expect("Open hidden db");
|
||||
db_hidden
|
||||
.init_schema_with_carrier(
|
||||
&salt_0,
|
||||
&kdf_params,
|
||||
&wrapped_0,
|
||||
&nonce_0,
|
||||
&tag_0,
|
||||
Some((
|
||||
"carrier.dat",
|
||||
1024 * 1024,
|
||||
&salt_1,
|
||||
&kdf_params,
|
||||
&wrapped_1,
|
||||
&nonce_1,
|
||||
&tag_1,
|
||||
&dek_0,
|
||||
&dek_1,
|
||||
)),
|
||||
)
|
||||
.expect("Init carrier schema");
|
||||
db_hidden.checkpoint().unwrap();
|
||||
|
||||
// Vergleiche Schemas via rusqlite
|
||||
let conn_std = rusqlite::Connection::open(&path_std).unwrap();
|
||||
let conn_hidden = rusqlite::Connection::open(&path_hidden).unwrap();
|
||||
|
||||
let get_schema_elements = |conn: &rusqlite::Connection| -> Vec<(String, String, Option<String>)> {
|
||||
let mut stmt = conn
|
||||
.prepare(
|
||||
"SELECT type, name, sql FROM sqlite_master
|
||||
WHERE type IN ('table', 'index') AND name NOT LIKE 'sqlite_%'
|
||||
ORDER BY type, name",
|
||||
)
|
||||
.unwrap();
|
||||
let rows = stmt
|
||||
.query_map([], |row| {
|
||||
Ok((
|
||||
row.get::<_, String>(0)?,
|
||||
row.get::<_, String>(1)?,
|
||||
row.get::<_, Option<String>>(2)?,
|
||||
))
|
||||
})
|
||||
.unwrap();
|
||||
rows.map(|r| r.unwrap()).collect()
|
||||
};
|
||||
|
||||
let schema_std = get_schema_elements(&conn_std);
|
||||
let schema_hidden = get_schema_elements(&conn_hidden);
|
||||
|
||||
assert_eq!(
|
||||
schema_std, schema_hidden,
|
||||
"M-05: SQLite-Schema (Tabellen, Indizes, DDL) muss zwischen Standard- und Hidden-Vault identisch sein"
|
||||
);
|
||||
|
||||
// Spalten- und Typinformationen vergleichen
|
||||
for table in &["meta", "nodes", "chunks"] {
|
||||
let get_table_info = |conn: &rusqlite::Connection| -> Vec<(i64, String, String, i64, Option<String>, i64)> {
|
||||
let mut stmt = conn.prepare(&format!("PRAGMA table_info({});", table)).unwrap();
|
||||
let rows = stmt
|
||||
.query_map([], |row| {
|
||||
Ok((
|
||||
row.get::<_, i64>(0)?,
|
||||
row.get::<_, String>(1)?,
|
||||
row.get::<_, String>(2)?,
|
||||
row.get::<_, i64>(3)?,
|
||||
row.get::<_, Option<String>>(4)?,
|
||||
row.get::<_, i64>(5)?,
|
||||
))
|
||||
})
|
||||
.unwrap();
|
||||
rows.map(|r| r.unwrap()).collect()
|
||||
};
|
||||
|
||||
let cols_std = get_table_info(&conn_std);
|
||||
let cols_hidden = get_table_info(&conn_hidden);
|
||||
assert_eq!(
|
||||
cols_std, cols_hidden,
|
||||
"M-05: Spalten und Typen für Tabelle '{}' müssen identisch sein",
|
||||
table
|
||||
);
|
||||
}
|
||||
|
||||
// Pragmas vergleichen (page_size, auto_vacuum, secure_delete)
|
||||
let get_pragma = |conn: &rusqlite::Connection, pragma: &str| -> i64 {
|
||||
conn.query_row(&format!("PRAGMA {};", pragma), [], |r| r.get(0))
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
get_pragma(&conn_std, "page_size"),
|
||||
get_pragma(&conn_hidden, "page_size")
|
||||
);
|
||||
assert_eq!(
|
||||
get_pragma(&conn_std, "auto_vacuum"),
|
||||
get_pragma(&conn_hidden, "auto_vacuum")
|
||||
);
|
||||
assert_eq!(
|
||||
get_pragma(&conn_std, "secure_delete"),
|
||||
get_pragma(&conn_hidden, "secure_delete")
|
||||
);
|
||||
|
||||
drop(conn_std);
|
||||
drop(conn_hidden);
|
||||
drop(db_std);
|
||||
drop(db_hidden);
|
||||
|
||||
let _ = std::fs::remove_file(&path_std);
|
||||
let _ = std::fs::remove_file(&path_hidden);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user