
# reverse_resonance_id
Self-checking symmetric tokens based on reversing `n²` and pairing it with fast integrity tags. The crate ships a zero-allocation core API, an optional CLI, and Criterion benches so you can validate throughput before rollout.
## Highlights
- Three schemes: baseline (CRC32 + Blake2s), HMAC (Blake2s) and salt+iter (slow hash w/ configurable work factor).
- Safe, pure-Rust implementation (Rust 1.70+ MSRV) with no `unsafe`.
- Strong test coverage including property and tamper tests, plus a 100k-token smoke test (opt-in).
- Optional features for CLI (`cli`), salted hashing (`salt-iter`), HMAC (`hmac`), serde integration, and in-memory key zeroisation (`zeroize`).
## Installation
```toml
[dependencies]
reverse_resonance_id = { version = "0.1.0", features = ["hmac", "salt-iter"] }
```
Feature flags:
| `baseline` | ✅ | Core CRC32 + Blake2s flow. |
| `hmac` | ✅ | Enables HMAC-Blake2s generation/verification. |
| `salt-iter` | ✅ | Enables salt+iter flow with secure randomness. |
| `cli` | ⛔ | Builds the `rrid` binary (`cargo install --features cli`). |
| `serde` | ⛔ | Derives `serde::Serialize/Deserialize` for structs that need it (used by CLI). |
| `zeroize` | ⛔ | Zeroizes stored secrets (Scheme enum, HMAC helper) when dropped. |
## Quick Start (Rust)
```rust
use reverse_resonance_id::{make_token_baseline, validate_token_baseline};
#[cfg(feature = "hmac")]
use reverse_resonance_id::{make_token_hmac, validate_token_hmac};
#[cfg(feature = "salt-iter")]
use reverse_resonance_id::{make_token_salt_iter, validate_token_salt_iter};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Baseline: CRC32 + truncated Blake2s (8 hex chars)
let baseline = make_token_baseline(33)?;
assert!(validate_token_baseline(baseline.as_str()));
// HMAC (Blake2s) with 64-bit tag (16 hex chars)
#[cfg(feature = "hmac")]
{
let key = hex::decode("00112233445566778899aabbccddeeff")?;
let hmac = make_token_hmac(33, &key, 16)?;
assert!(validate_token_hmac(hmac.as_str(), &key, 16));
}
// Salted iterative hash (default salt=4 bytes, iters=2048)
#[cfg(feature = "salt-iter")]
{
let slow = make_token_salt_iter(33, 4, 2_048)?;
assert!(validate_token_salt_iter(slow.as_str()));
}
Ok(())
}
```
Scheme formats:
| Baseline | `<n2>-<rev>-<crc32hex8>-<blake2s8hex>` |
| HMAC | `<n2>-<rev>-<hmac_blake2s_hex>` |
| Salt+Iter | `<n2>-<rev>-<salt_hex>-<iters>-<tag8hex>` |
Where `n2 = n * n` as decimal string, `rev` is that string reversed, and the payload hashed is `"{n2}|{rev}"`.
## CLI
Enable the `cli` feature to build the `rrid` binary:
```sh
cargo install --path . --features cli
```
### Generate
```sh
$ rrid make --scheme baseline 33
{"token":"1089-9801-f7961616-283a12c9","scheme":"baseline","gen_time_ms":0.088709}
$ rrid make --scheme hmac --key 00112233445566778899aabbccddeeff --tag-len 16 33
{"token":"1089-9801-6d779ec117c17c71","scheme":"hmac","gen_time_ms":0.10254100000000001}
$ rrid make --scheme salt-iter --salt-len 4 --iters 2048 33
{"token":"1089-9801-b453dac8-2048-8cebd230","scheme":"salt-iter","gen_time_ms":12.504375}
```
### Verify
```sh
$ rrid verify --scheme baseline 1089-9801-f7961616-283a12c9
{"token":"1089-9801-f7961616-283a12c9","scheme":"baseline","gen_time_ms":0.088917}
```
The command exits with code `0` when validation succeeds and `1` otherwise. JSON always contains `token`, `scheme`, and the measured runtime in milliseconds.
## Errors
Token generation returns `Result<Token, RRIDError>`. Validation helpers return `bool` (`false` on any error). `RRIDError` variants cover invalid user IDs, format/parse problems, reversed-string mismatches, tag mismatches, and cryptographic errors. Convert or display them directly for logging/auditing.
## Security Notes
- **Baseline**: Fast and deterministic, but only a 32-bit CRC + 32-bit Blake2s tag. Best for human-readable, low-risk use-cases.
- **HMAC**: Requires a server-side secret. Default tag length is 16 hex chars (64 bits). Increase `tag_len` for harder brute force. Enable the `zeroize` feature to erase in-memory keys on drop.
- **Salt+Iter**: Keyless, time-hardening defence against brute force. Defaults to 2048 iterations; adjust upward for higher security (but note the slower throughput and DoS trade-offs).
- All hex digests are lowercase. Always compare using the provided helpers to avoid subtle mistakes.
- For long-term, high-assurance deployments, consider layering stronger authentication (e.g., Ed25519 signatures) on top—this crate documents the core rev(n²) idea.
## Benchmarks
Measured with `cargo bench` on Rust `1.88.0` (release build) on the developer machine. Throughput counts complete generate+validate pairs.
| Baseline | 100k tokens / batch | ~595k tokens/sec |
| HMAC (tag 16) | 50k tokens / batch | ~506k tokens/sec |
| Salt+Iter (512 iters) | 5k tokens / batch | ~7.9k tokens/sec |
| Salt+Iter (1024 iters) | 5k tokens / batch | ~3.9k tokens/sec |
| Salt+Iter (2048 iters) | 5k tokens / batch | ~2.0k tokens/sec |
| Salt+Iter (4096 iters) | 5k tokens / batch | ~0.93k tokens/sec |
Use the benches to evaluate your own hardware (`cargo bench`). Plots are stored under `target/criterion/`.
## Testing & QA
```sh
cargo fmt
cargo clippy --all-targets --all-features
cargo test
cargo bench # runs Criterion suites
cargo test -- --ignored # runs the 100k-token smoke test
```
The test suite includes:
- Round-trip, tamper, and uniqueness checks for every scheme.
- Property tests with Proptest.
- Deterministic RNG tests for salt generation.
- A long-running `#[ignore]` bulk test covering 100k tokens and salt iter smoke coverage.
## Actix Web Integration Snippet
```rust,ignore
use actix_web::{dev::Payload, error::ErrorUnauthorized, FromRequest, HttpRequest};
use futures_util::future::{ready, Ready};
use reverse_resonance_id::validate_token_hmac;
pub struct RridToken(String);
impl FromRequest for RridToken {
type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
const KEY: &[u8] = b"0123456789abcdef0123456789abcdef";
let header = req
.headers()
.get("x-rrid-token")
.and_then(|v| v.to_str().ok());
match header {
Some(token) if validate_token_hmac(token, KEY, 16) => {
ready(Ok(RridToken(token.to_owned())))
}
_ => ready(Err(ErrorUnauthorized("invalid rrid token"))),
}
}
}
```
## License
Dual-licensed under MIT or Apache-2.0. See `LICENSE-MIT` and `LICENSE-APACHE` for details.