pub struct Nonce {
pub value: String,
pub created_at: i64,
}Expand description
A replay nonce used for ACME protocol anti-replay protection.
§ACME Protocol Compliance
According to RFC 8555, nonces are used to prevent replay attacks:
- Each nonce is 32 random bytes from the system CSPRNG, base64url-encoded without padding — the octet-string form §6.5.1 requires, and 256 bits like every other non-guessable value in this tree
- Nonces are generated for every response
- Clients must include a valid nonce in their requests
- Nonces are single-use and expire after a TTL period
§Security Considerations
- Nonces are stored in the database with timestamps
- Expired nonces are automatically cleaned up
- Single-use enforcement prevents replay attacks
- Time-to-live limits prevent indefinite nonce accumulation
§Database Storage
Nonces are stored in the nonces table with:
value: The base64url nonce stringcreated_at: Unix timestamp when the nonce was created
§Lifecycle
- New nonce created for each response
- Nonce saved to database
- Client uses nonce in subsequent request
- Nonce verified and consumed (single-use)
- Expired nonces automatically cleaned up
Fields§
§value: String§created_at: i64Implementations§
Source§impl Nonce
impl Nonce
pub fn new() -> Self
pub async fn save(&self, database: &Database) -> Result<(), Error>
Sourcepub async fn verify(
nonce: &str,
database: &Database,
ttl: Duration,
) -> Result<bool, Error>
pub async fn verify( nonce: &str, database: &Database, ttl: Duration, ) -> Result<bool, Error>
Consumes nonce if it is live: a single DELETE whose rows_affected
decides, so two concurrent replays cannot both succeed.
Takes &str rather than String — it only ever binds a reference, and
this runs on every signed POST, which is the hottest path in the server.
Sourcepub async fn count(database: &Database) -> Result<i64, Error>
pub async fn count(database: &Database) -> Result<i64, Error>
How many nonce rows exist right now.
The one thing worth showing about this table: individual values are
bearer credentials and are never listed (see the note on
fingerprint), but the count is a useful health signal — it should
hover around the request rate times the TTL, and a number far above
that means the reaper is not running.
pub async fn cleanup(database: &Database, ttl: Duration) -> Result<u64, Error>
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Nonce
impl RefUnwindSafe for Nonce
impl Send for Nonce
impl Sync for Nonce
impl Unpin for Nonce
impl UnsafeUnpin for Nonce
impl UnwindSafe for Nonce
Blanket Implementations§
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<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
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