paserk
Platform-Agnostic Serialized Keys (PASERK) for PASETO in Rust.
PASERK is a standard format for serializing keys used with PASETO tokens. This crate provides a type-safe, idiomatic Rust implementation of the PASERK specification.
Features
- Full PASERK specification support - All 11 PASERK types across all 4 versions (K1-K4)
- Type-safe API - Version markers prevent mixing keys from different PASETO versions
- Security-first design - Keys are zeroized on drop, no unsafe code, constant-time comparisons
- Flexible feature flags - Enable only the versions you need to minimize dependencies
- Ergonomic builders - Fluent APIs for password-based key wrapping with preset security profiles
Quick Start
Add paserk to your Cargo.toml:
[]
= "0.1"
By default, K4 (the recommended version) and the ergonomic prelude are enabled. See Feature Flags for other options.
Basic Usage
use *;
// Create a symmetric key from raw bytes
let key = from;
// Serialize to PASERK format
let paserk_string = key.to_string;
assert!;
// Parse a PASERK string
let parsed: = paserk_string.parse.unwrap;
// Compute a key identifier
let key_id = from;
assert!;
Password-Based Key Wrapping
Protect keys with a password using Argon2id (K2/K4) or PBKDF2 (K1/K3):
use *;
let key = from;
// Wrap with preset security profile
let wrapped = moderate
.try_wrap?;
// Serialize the wrapped key
let wrapped_string = wrapped.to_string;
assert!;
// Later, unwrap the key
let unwrapped = wrapped.try_unwrap?;
Key Wrapping with Another Key
Wrap a key using PIE (Platform-Independent Encryption):
use *;
let key_to_wrap = from;
let wrapping_key = from;
// Wrap the key
let wrapped = wrap;
assert!;
// Unwrap the key
let unwrapped = wrapped.try_unwrap?;
Public Key Encryption (Seal)
Encrypt a symmetric key to a public key:
use *;
let symmetric_key = from;
// Generate or load a secret key (contains both secret and public parts)
let secret_key = from;
// Seal the symmetric key to the public key
let sealed = seal;
assert!;
// Unseal with the secret key
let unsealed = sealed.try_unseal?;
PASERK Types
| Type | Format | Description |
|---|---|---|
local |
k{v}.local.{data} |
Symmetric encryption key |
public |
k{v}.public.{data} |
Public verification key |
secret |
k{v}.secret.{data} |
Secret signing key |
lid |
k{v}.lid.{data} |
Local key identifier |
pid |
k{v}.pid.{data} |
Public key identifier |
sid |
k{v}.sid.{data} |
Secret key identifier |
local-wrap |
k{v}.local-wrap.pie.{data} |
PIE-wrapped symmetric key |
secret-wrap |
k{v}.secret-wrap.pie.{data} |
PIE-wrapped secret key |
local-pw |
k{v}.local-pw.{data} |
Password-wrapped symmetric key |
secret-pw |
k{v}.secret-pw.{data} |
Password-wrapped secret key |
seal |
k{v}.seal.{data} |
PKE-encrypted symmetric key |
Versions
PASERK supports four versions corresponding to PASETO versions:
| Version | Algorithms | Use Case |
|---|---|---|
| K1 | RSA-4096, AES-256-CTR, HMAC-SHA384, PBKDF2 | NIST compliance (legacy) |
| K2 | Ed25519, XChaCha20, BLAKE2b, Argon2id | Sodium-based (PASETO V2) |
| K3 | P-384, AES-256-CTR, HMAC-SHA384, PBKDF2 | NIST compliance (modern) |
| K4 | Ed25519, XChaCha20, BLAKE2b, Argon2id | Recommended for new applications |
Version Compatibility
| Type | K1 | K2 | K3 | K4 |
|---|---|---|---|---|
local |
✓ | ✓ | ✓ | ✓ |
public |
✓ | ✓ | ✓ | ✓ |
secret |
— | ✓ | ✓ | ✓ |
lid |
✓ | ✓ | ✓ | ✓ |
pid |
✓ | ✓ | ✓ | ✓ |
sid |
— | ✓ | ✓ | ✓ |
local-wrap |
✓ | ✓ | ✓ | ✓ |
secret-wrap |
— | ✓ | ✓ | ✓ |
local-pw |
✓ | ✓ | ✓ | ✓ |
secret-pw |
— | ✓ | ✓ | ✓ |
seal |
✓ | ✓ | ✓ | ✓ |
Note: K1 uses RSA which has no separate secret key type in PASETO V1.
Feature Flags
Enable specific PASERK versions based on your needs:
# K4 + prelude (default, recommended for new applications)
= "0.1"
# Multiple specific versions
= { = "0.1", = ["k2", "k4"] }
# All versions
= { = "0.1", = ["all-versions"] }
# Minimal (no prelude, for power users)
= { = "0.1", = false, = ["k4"] }
| Feature | Description | Dependencies Added |
|---|---|---|
k1 |
NIST original (RSA-based) | sha2, hmac, aes, ctr, pbkdf2, rsa |
k2 |
Sodium original | blake2, chacha20, argon2, x25519-dalek, ed25519-dalek |
k3 |
NIST modern (P-384-based) | sha2, hmac, aes, ctr, pbkdf2, p384 |
k4 |
Sodium modern (default) | blake2, chacha20, argon2, x25519-dalek, ed25519-dalek |
prelude |
Ergonomic imports and builders (default) | — |
all-versions |
Enable K1, K2, K3, K4 | All of the above |
The Prelude
The prelude module provides a single import for common usage:
use *;
This gives you access to:
- All key types:
PaserkLocal,PaserkPublic,PaserkSecret - Key identifiers:
PaserkLocalId,PaserkPublicId,PaserkSecretId - Wrapping types:
PaserkLocalWrap,PaserkSecretWrap,PaserkLocalPw,PaserkSecretPw,PaserkSeal - Version markers:
K1,K2,K3,K4 - Fluent builders:
LocalPwBuilder,SecretPwBuilderwith preset security profiles - Error types:
PaserkError,PaserkResult
Cryptographic Operations
Key Wrapping (PIE Protocol)
| Version | Encryption | Authentication |
|---|---|---|
| K1/K3 | AES-256-CTR | HMAC-SHA384 (48-byte tag) |
| K2/K4 | XChaCha20 | BLAKE2b (32-byte tag) |
Password-Based Key Wrapping (PBKW)
| Version | KDF | Encryption | Authentication |
|---|---|---|---|
| K1/K3 | PBKDF2-SHA384 | AES-256-CTR | HMAC-SHA384 |
| K2/K4 | Argon2id | XChaCha20 | BLAKE2b |
Security Profiles (for K2/K4 Argon2id):
| Profile | Memory | Iterations | Use Case |
|---|---|---|---|
interactive() |
64 MiB | 2 | Online authentication |
moderate() |
256 MiB | 3 | Default, balanced security |
sensitive() |
1 GiB | 4 | High-value secrets |
Public Key Encryption (Seal)
| Version | Key Exchange | Encryption | Authentication |
|---|---|---|---|
| K1 | RSA-4096 KEM | AES-256-CTR | HMAC-SHA384 |
| K2/K4 | X25519 ECDH | XChaCha20 | BLAKE2b |
| K3 | P-384 ECDH | AES-256-CTR | HMAC-SHA384 |
Security
This crate prioritizes security:
- Memory safety: All key material is zeroized on drop using the
zeroizecrate - No unsafe code: Enforced via
#![forbid(unsafe_code)] - Constant-time operations: Secret comparisons use the
subtlecrate - Redacted debug output:
Debugimplementations hide sensitive key material - Authenticated encryption: All wrapping operations use AEAD-equivalent constructions
- Strict lints:
unwrap,expect, andpanicare denied
API Documentation
Full API documentation is available on docs.rs.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Related Projects
- PASETO - Platform-Agnostic Security Tokens
- PASERK Specification - The official PASERK specification