sealwd
sealwd provides small, focused primitives for handling secrets safely in Rust.
Designed specifically for server-side authentication systems, it enforces a strict separation between low-entropy user passwords and high-entropy machine-generated tokens. It handles memory zeroization, secure generation, policy validation, forward-compatible hashing, and optional encryption at rest.
Core Philosophy & Security Model
Passwords and tokens serve different purposes and require different cryptographic treatments:
- Passwords are low-entropy secrets provided by users. They are hashed using Argon2id (slow, memory-hard) to resist brute-force attacks.
- Tokens are high-entropy secrets generated by the system (e.g., session IDs, API keys, OAuth assertions). They are hashed using BLAKE3 (fast) with a server-side pepper. Using token hashing for passwords is mathematically insecure and intentionally unsupported by this crate.
Features
- Explicit Secret Types: Distinct types for
Password, stack-allocated fixed-sizeToken<LEN>, and heap-allocated dynamically-sizedGenericToken. - Memory Safety: All secret containers automatically implement explicit memory zeroization on drop via the
zeroizeecosystem. - Password Policies: Configurable rules for generation and validation (length, character classes).
- Self-Describing Hashes: Binary serializable hashes (
PasswordHash,TokenHash) with embedded algorithm versions for forward compatibility. - Encryption at Rest (Optional): AEAD encryption (XChaCha20-Poly1305 or AES-256-GCM-SIV) via the
encryptionfeature, preserving domain types using compile-time marker validation (EncryptedToken<T>). - Framework Integrations (Optional): Direct
BYTEAmappings for PostgreSQL viasqlx, and context-awareserdeserialization (clean Base64 for human-readable formats, raw bytes for binary protocols).
Usage
Managing Passwords
use ;
// 1. Define a policy
let policy = with_sane_defaults;
// 2. Generate a secure random password satisfying the policy
let password = random.unwrap;
// 3. Hash the password for storage (uses Argon2id automatically)
let hash = password.to_default_hash.unwrap;
// 4. Verify a login attempt
assert!;
Managing High-Entropy Tokens
sealwd provides two token variants depending on your layout requirements:
Token<const LEN: usize>: Optimized, stack-allocated fixed-size container utilizing constant generics.GenericToken: Heap-allocated dynamically-sized container ideal for runtime-determined lengths or external keys.
Both implement the TokenMaterial trait, sharing uniform hashing and encoding APIs.
Using Fixed-Size Stack Tokens (e.g., Session IDs, Refresh Tokens)
use ;
// 1. Generate a 32-byte cryptographic token on the stack
let token = random.unwrap;
// 2. Export to URL-safe Base64 string to send to the client
let encoded = token.to_base64;
// 3. Hash with a server-side pepper for database storage (uses BLAKE3)
let pepper = b"my-secret-server-pepper-value";
let token_hash = token.to_default_hash;
// 4. Verify an incoming client token directly
let client_token = from_base64.unwrap;
assert!;
Using Dynamically-Sized Heap Tokens (e.g., OAuth Assertions, Ingested API Keys)
use ;
let pepper = b"my-secret-server-pepper-value";
// Instantiate from a runtime-received variable length slice
let external_key = b"some-arbitrary-length-incoming-api-key-payload";
let token = from_bytes;
// Or generate a secure random dynamic token of specific length
let dynamic_token = random.unwrap;
// Hash securely using uniform token pipelines
let token_hash = token.to_default_hash;
Encryption at Rest (Requires encryption feature)
When storing tokens that must be reversible (e.g., third-party external API keys), you can encrypt them before storage. The EncryptedToken<T> container uses PhantomData to enforce compile-time alignment back to your native domain model upon decryption.
use ;
let token = random.unwrap;
let encryption_key = b"thisisa32bytekeyforrustcryptolib";
// Encrypt the token into a type-safe EncryptedToken<Token<16>> wrapper
let encrypted = token.encrypt.unwrap;
// Decrypt back to your strictly-typed Token<16> directly
let decrypted: = encrypted.decrypt.unwrap;
Feature Flags
encryption: Enables thecryptomodule, providingEncryptedPasswordandEncryptedToken<T>wrappers backed by authenticated AEAD ciphers.serde: Enables transparent serialization/deserialization for domain types. Intelligently routes through URL-safe Base64 for human-readable structures (JSON) and raw byte arrays for binary networks (Bincode/MessagePack).sqlx: Implementssqlx::Type,Encode, andDecodeallowing hashes and encrypted types to be used directly with database queries without manual container unpacking (maps toBYTEAin Postgres).
License
Apache-2.0