
# Introduction

> unsecure is a set of cryptographic utilities built on the Web Crypto API: zero dependencies, one entry point per module, and one typed error.

`unsecure` is a collection of runtime-agnostic, cryptographically secure utilities. The name is a joke. The defaults are not.

Everything here is built on the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) and the platform's own CSPRNG. There are no runtime dependencies, no Node built-ins, and no WebAssembly, so the same code runs in Node, Bun, Deno, Cloudflare Workers and browsers.

## What is in the box

| Family                                       | Functions                                                                       |
| -------------------------------------------- | ------------------------------------------------------------------------------- |
| [Hashing and MAC](/crypto/hashing)           | `hash`, `hmac`, `hmacVerify`, `importHmacKey`                                   |
| [Key derivation](/crypto/key-derivation)     | `hkdf`, `importHkdfKey`                                                         |
| [Password hashing](/crypto/password-hashing) | `argon2`, `argon2Hash`, `argon2Verify`, `argon2NeedsRehash`                     |
| [One-time passwords](/crypto/otp)            | `hotp`, `totp`, their verifies, `generateOTPSecret`, `otpauthURI`               |
| [UUID](/generate/uuid)                       | `uuidv4`, `uuidv7`, `createUUIDv7Generator`, `uuidv7Timestamp`, the type guards |
| [Secrets](/generate/secrets)                 | `secureGenerate`, `secureCompare`, `entropy`                                    |
| [Sanitize](/safety/sanitize)                 | `sanitizeObject`, `sanitizeObjectCopy`, `safeJsonParse`                         |
| [Random](/generate/random)                   | `secureRandomNumber`, `secureRandomBytes`, `secureShuffle`, `randomJitter`      |
| [Codecs](/safety/codecs)                     | `Hex`, `Base64`, `Base32` and their flat `stringify` / `parse` functions        |
| [Errors](/safety/errors)                     | `UnsecureError` and its code set                                                |

## Two rules that run through everything

**Verification never throws on untrusted input.** `secureCompare`, `hmacVerify`, `hotpVerify`, `totpVerify` and `argon2Verify` return `false` for a missing header, a malformed signature or a wrong-typed value from a JSON body. They throw only for something you control: an empty secret, an unsupported algorithm, an out-of-range window. So a `try` / `catch` around a verify is about your own configuration, never about the request.

**One error class, one code set.** Every failure is an [`UnsecureError`](/safety/errors) with a `code` you can branch on. A native `TypeError` escaping the library is a bug.

## What it looks like

```ts
import { argon2Hash, argon2Verify } from "unsecure/argon2";
import { hmacVerify } from "unsecure/hmac";
import { uuidv7 } from "unsecure/uuid";

const stored = await argon2Hash("correct horse battery staple");
// "$argon2id$v=19$m=19456,t=2,p=1$…$…"

await argon2Verify(stored, "correct horse battery staple"); // true
await argon2Verify(stored, "hunter2"); // false

await hmacVerify(secret, body, request.headers.get("x-signature")); // boolean

uuidv7(); // "01a076ba-1e53-7411-8518-84905f353e3d"
```

## What is not in the box

JWT, JWS, JWE and JWK are intentionally out of scope, and will stay that way. [unjwt](https://unjwt.s94.dev) covers the whole JOSE toolset with the same runtime-agnostic, Web Crypto approach; the two libraries are meant to sit side by side.

## Where to go next

::card-group
::card{title="Installation" icon="i-lucide-download" to="/getting-started/installation"}
Install the package, pick between the barrel and the subpaths, or import from a CDN.
::
::card{title="Quickstart" icon="i-lucide-rocket" to="/getting-started/quickstart"}
Five short tasks, end to end, with the output each one prints.
::
::card{title="Migrating to 0.3" icon="i-lucide-arrow-right-left" to="/getting-started/migration"}
What changed since 0.2.3, and what you have to edit.
::
::card{title="Recipes" icon="i-lucide-code" to="/examples"}
Webhook verification, login with 2FA, password storage, safe JSON.
::
::
