unsecure is a collection of runtime-agnostic cryptographically-secure utilities. (ba dum tss 🥁)
Zero dependencies, built on the Web Crypto API, one module per subpath so a CDN import ships only what you use, and one typed error for everything that can go wrong.
Documentation: unsecure.s94.dev
# ✨ Auto-detect (supports npm, yarn, pnpm, deno and bun)
npx nypm install unsecureRuns on Node.js ^22.12 or >=24, and on any runtime with Web Crypto (Bun, Deno, Cloudflare Workers, browsers).
import { argon2Hash, argon2Verify, hmacVerify, totpVerify, uuidv7 } from "unsecure";
// Store and check a password (argon2id, OWASP defaults, PHC string)
const stored = await argon2Hash(plaintext);
const ok = await argon2Verify(stored, submitted);
// Verify a webhook signature in constant time; a missing header is `false`, never a throw
const valid = await hmacVerify(secret, body, request.headers.get("x-signature"));
// Check a 2FA code; replay is refused when you pass back the last accepted step
const result = await totpVerify(secret, code, { lastAccepted: user.lastOtpStep });
// A time-ordered identifier
const id = uuidv7();Every module is also its own entry point:
import { hkdf } from "https://esm.sh/unsecure/hkdf";
import { base64Parse } from "https://esm.sh/unsecure/utils";| Module | Functions | Docs |
|---|---|---|
unsecure/hash, unsecure/hmac |
hash, hmac, hmacVerify, importHmacKey |
Hashing & MAC |
unsecure/hkdf |
hkdf, importHkdfKey |
Key derivation |
unsecure/argon2 |
argon2, argon2Hash, argon2Verify, argon2NeedsRehash |
Password hashing |
unsecure/otp |
hotp, hotpVerify, totp, totpVerify, generateOTPSecret, otpauthURI |
One-time passwords |
unsecure/uuid |
uuidv4, uuidv7, createUUIDv7Generator, uuidv7Timestamp, isUUIDv4, isUUIDv7 |
UUID |
unsecure/generate, unsecure/compare, unsecure/entropy |
secureGenerate, secureCompare, entropy |
Secrets |
unsecure/sanitize |
sanitizeObject, sanitizeObjectCopy, safeJsonParse |
Sanitize |
unsecure/random |
createSecureRandomGenerator, secureRandomNumber, secureRandomBytes, secureShuffle, randomJitter |
Random |
unsecure/utils |
hexStringify / hexParse, base64Stringify / base64Parse, base32Stringify / base32Parse, Hex, Base64, Base32 |
Codecs |
unsecure/errors |
UnsecureError |
Errors |
- Everything the library throws is an
UnsecureErrorwith a machine-readablecode; branch on the code, not the message. - Verification functions (
secureCompare,hmacVerify,hotpVerify,totpVerify,argon2Verify) never throw on untrusted input. They returnfalse; a throw means your own configuration is wrong. - Decoding is strict and canonical by default, inputs are range-checked at the boundary, and behavior is identical on every runtime and backend.
Looking for JWT, JWS, JWE or JWK? That is intentionally not here. unjwt covers the whole JOSE toolset with the same runtime-agnostic, Web Crypto approach.
Upgrading from an earlier release? The docs keep the migration guides.
local development
Inspired by DeepSource Corp work.