pub struct MessageAuthenticator { /* private fields */ }Expand description
Production-quality message authenticator with:
- HMAC-FNV64 signing / verification (three algorithm variants).
- Replay attack prevention via a bounded nonce window.
- Key expiry and atomic key rotation.
- Configurable
AuthPolicyenforcement. - Monotonic per-key sequence numbers.
- Cumulative statistics and drainable audit log.
§Example
use ipfrs_network::message_authenticator::{
AuthAlgorithm, AuthKey, AuthPolicy, MessageAuthenticator,
};
let mut auth = MessageAuthenticator::new(vec![AuthPolicy::RequireAll], 256);
let key = AuthKey::new("k1", b"super-secret".to_vec(), 0, None, AuthAlgorithm::HmacFnv64);
auth.add_key(key).unwrap();
let msg = auth.sign(b"hello world".to_vec(), "k1", 1_000_000).unwrap();
auth.verify(&msg, 1_000_000).unwrap();Implementations§
Source§impl MessageAuthenticator
impl MessageAuthenticator
Sourcepub fn new(policies: Vec<AuthPolicy>, replay_window_size: usize) -> Self
pub fn new(policies: Vec<AuthPolicy>, replay_window_size: usize) -> Self
Create a new MessageAuthenticator.
policies— list ofAuthPolicyvariants to enforce.replay_window_size— maximum number of nonces retained for replay detection.
§Panics
Does not panic; replay_window_size == 0 is accepted but provides no
replay protection.
Sourcepub fn add_key(&mut self, key: AuthKey) -> Result<(), AuthError>
pub fn add_key(&mut self, key: AuthKey) -> Result<(), AuthError>
Add a new key to the keystore.
Fails with AuthError::KeyNotFound if a key with the same ID already
exists (use rotate_key for atomic replacement).
Sourcepub fn remove_key(&mut self, key_id: &str) -> Result<(), AuthError>
pub fn remove_key(&mut self, key_id: &str) -> Result<(), AuthError>
Remove a key from the keystore.
Returns AuthError::KeyNotFound if no such key exists.
Sourcepub fn rotate_key(
&mut self,
old_id: &str,
new_key: AuthKey,
) -> Result<(), AuthError>
pub fn rotate_key( &mut self, old_id: &str, new_key: AuthKey, ) -> Result<(), AuthError>
Atomically replace the key identified by old_id with new_key.
The sequence counter is reset to 1 for the new key.
Returns AuthError::KeyNotFound if old_id is not in the keystore.
Sourcepub fn sign(
&mut self,
payload: Vec<u8>,
key_id: &str,
current_ts: u64,
) -> Result<SignedMessage, AuthError>
pub fn sign( &mut self, payload: Vec<u8>, key_id: &str, current_ts: u64, ) -> Result<SignedMessage, AuthError>
Sign payload using the key identified by key_id.
- A fresh nonce is generated via
xorshift64. - The signature is computed per the key’s
AuthAlgorithm. - The per-key sequence counter is incremented atomically.
§Errors
AuthError::KeyNotFound— unknown key.AuthError::KeyExpired— key has passed its expiry.AuthError::NonceExhausted— PRNG state wrapped to zero (extremely unlikely in practice).AuthError::KeyRotationRequired— (via policy check) key age exceeds the rotation threshold.
Sourcepub fn verify(
&mut self,
msg: &SignedMessage,
current_ts: u64,
) -> Result<(), AuthError>
pub fn verify( &mut self, msg: &SignedMessage, current_ts: u64, ) -> Result<(), AuthError>
Verify the authenticity of msg at time current_ts.
Checks (in order):
- Key exists in the keystore.
- Key has not expired.
- Nonce has not been replayed.
- Sequence number is valid (when
SequentialNoncepolicy is active). - Signature matches the recomputed value.
On success the nonce is recorded and statistics are updated.
Sourcepub fn check_replay(&self, nonce: u64) -> bool
pub fn check_replay(&self, nonce: u64) -> bool
Return true if nonce is present in the current replay window.
Sourcepub fn record_nonce(&mut self, nonce: u64)
pub fn record_nonce(&mut self, nonce: u64)
Add nonce to the replay window, evicting the oldest entry if full.
Sourcepub fn expire_keys(&mut self, current_ts: u64) -> Vec<String>
pub fn expire_keys(&mut self, current_ts: u64) -> Vec<String>
Remove all keys whose expires_at is ≤ current_ts.
Returns the IDs of all removed keys.
Sourcepub fn drain_events(&mut self) -> Vec<String>
pub fn drain_events(&mut self) -> Vec<String>
Drain the internal audit log, returning all accumulated events.
The log is cleared after this call.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for MessageAuthenticator
impl RefUnwindSafe for MessageAuthenticator
impl Send for MessageAuthenticator
impl Sync for MessageAuthenticator
impl Unpin for MessageAuthenticator
impl UnsafeUnpin for MessageAuthenticator
impl UnwindSafe for MessageAuthenticator
Blanket Implementations§
impl<T> Allocation for T
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§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