Skip to main content

HashChainAuditor

Struct HashChainAuditor 

Source
pub struct HashChainAuditor { /* private fields */ }
Expand description

Auditor with a hash chain: all logs are linked by SHA-256 chained hashes, supporting tamper detection.

§Tamper-Evidence Mechanism

  1. Each record’s current_hash = SHA256(prev_hash || sql || user || timestamp)
  2. The prev_hash of the next record equals the current_hash of the previous record
  3. Any modification to a historical record changes current_hash, which then mismatches the prev_hash of the next record
  4. Deleting a middle record breaks the chain; inserting a record changes all subsequent hashes

§Example

use sz_orm_audit::{HashChainAuditor, SqlAuditContext};

let mut auditor = HashChainAuditor::new();
auditor.log(&SqlAuditContext {
    sql: "SELECT * FROM users".to_string(),
    user: "admin".to_string(),
    timestamp: 1000,
});
// Verify chain integrity
assert!(auditor.verify().is_ok());

Implementations§

Source§

impl HashChainAuditor

Source

pub fn new() -> Self

Create an empty hash chain auditor

Source

pub fn log(&self, ctx: &SqlAuditContext)

Append an audit log to the end of the hash chain.

  • If the chain is empty, uses GENESIS_HASH as prev_hash
  • Otherwise uses the current_hash of the last record as prev_hash

The SQL is first masked by mask_sensitive before being written to the chain, ensuring that the stored audit logs contain no sensitive information.

Source

pub fn get_entries(&self) -> Vec<HashChainEntry>

Return a snapshot (clone) of all log entries

Source

pub fn len(&self) -> usize

Return the number of log entries

Source

pub fn is_empty(&self) -> bool

Whether the auditor is empty

Source

pub fn verify(&self) -> Result<(), String>

Verify the integrity of the hash chain.

Checks performed:

  1. The prev_hash of the first record equals GENESIS_HASH
  2. The current_hash of each record equals compute_hash(prev_hash, entry)
  3. The prev_hash of each adjacent record equals the current_hash of the previous record
§Return value
  • Ok(()): the chain is intact and has not been tampered with
  • Err(reason): the chain has been tampered with; reason describes the location and type of the first anomaly
Source

pub fn flush(&self, path: &str) -> Result<usize, String>

Persist the hash chain to a JSONL file (one JSON per line).

Returns the number of entries written.

Trait Implementations§

Source§

impl Default for HashChainAuditor

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.