A secure, type-safe implementation of PASETO (Platform-Agnostic Security Tokens) v4 and PASERK (Platform-Agnostic Serialized Keys) for Zig.
- PASETO v4.local: Symmetric encryption with ChaCha20-Poly1305
- PASETO v4.public: Digital signatures with Ed25519
- PASERK: Complete key management and serialization
- Builder Pattern: Secure token creation with sensible defaults
- Parser Pattern: Safe token verification and claims extraction
- Type Safety: Prevent key type confusion attacks
- Memory Safe: Secure key handling with explicit zeroing
const std = @import("std");
const paseto = @import("paseto");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Generate keys
var local_key = paseto.LocalKey.generate();
defer local_key.deinit();
// Create token with secure defaults (1-hour expiration)
var builder = paseto.createLocalBuilder(allocator);
defer builder.deinit();
_ = try builder.withDefaults();
_ = try builder.setIssuer("myapp");
_ = try builder.setSubject("user123");
const token = try builder.buildLocal(&local_key);
defer allocator.free(token);
// Verify token
var parser = paseto.createParser(allocator);
var claims = try parser.parseLocal(token, &local_key, null, null);
defer claims.deinit(allocator);
std.debug.print("Issuer: {s}\n", .{claims.issuer.?});
}Add to your build.zig:
const paseto = b.dependency("paseto", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("paseto", paseto.module("paseto"));Symmetric encryption for trusted environments:
- Algorithm: ChaCha20-Poly1305 AEAD
- Key Derivation: BLAKE2b
- Use Case: Single application or trusted network
Digital signatures for distributed systems:
- Algorithm: Ed25519
- Use Case: Multiple services, public verification
Complete key management with serialization formats:
// Serialize keys
const local_paserk = try paseto.paserk.serializeLocalKey(allocator, &key);
const public_paserk = try paseto.paserk.serializePublicKey(allocator, &keypair.public);
// Key identifiers
const lid = paseto.LocalKeyId.fromLocalKey(key.bytes());
const lid_paserk = try lid.serialize(allocator);
// Password-based key wrapping
const wrapped = try paseto.paserk.password.wrapLocalKeyWithPassword(
allocator, &key, "password", .{}
);- Constant-time comparisons prevent timing attacks
- Secure memory handling with explicit key zeroing
- Type-safe APIs prevent key misuse
- Secure defaults: 1-hour expiration, automatic timestamps
- Footer and implicit assertion support for additional authenticated data
createLocalBuilder()/createPublicBuilder()- Token creationcreateParser()- Token verificationLocalKey.generate()/KeyPair.generate()- Key generation
withDefaults()- Apply secure defaultssetIssuer(),setSubject(),setAudience()- Standard claimssetExpiration(),setIssuedAt()- Time-based claimssetClaim(),setClaimNumber()- Custom claimssetFooter(),setImplicit()- Additional authenticated data
parseLocal()/parsePublic()- Token verificationsetValidateTime()- Enable/disable time validationsetLeeway()- Clock skew tolerance
zig build test # Run test suite
zig build example # Run example program- Key Management: Store keys securely, use PASERK for serialization
- Time Validation: Enable for production use
- Transport Security: Use HTTPS for token transmission
- Token Lifetime: Use appropriate expiration times
- Implicit Assertions: Include context-specific data when needed
MIT License - see LICENSE file for details.
Issues and pull requests welcome. Please ensure all tests pass and follow existing code style.