
# Quickstart

> Five short tasks with the exact output each one prints, from hashing a string to checking a one-time password.

Every snippet below is a complete program. The comment after each call is what it actually returns.

## Hash a string

```ts
import { hash } from "unsecure/hash";

await hash("hello world");
// "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"

await hash("hello world", { returnAs: "base64" });
// "uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek="

await hash("hello world", { algorithm: "SHA-512" });
// "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff…"
```

A `string` in gives you hex out. Bytes in give you bytes out. Say `returnAs` when you want something else.

[More on hashing](/crypto/hashing/hash)

## Sign and verify a message

```ts
import { hmac, hmacVerify } from "unsecure/hmac";

const signature = await hmac("secret-key", "payload");
// "10aa2e1c2538464ff75f0647271e3ba746bca3fcdeaf322c581bf5851e8cddb7"

await hmacVerify("secret-key", "payload", signature); // true
await hmacVerify("secret-key", "payload", null); // false
await hmacVerify("secret-key", "payload", "00".repeat(32)); // false
```

`hmacVerify` compares in constant time and never throws on a bad signature. A `null` header is a `false`, not an exception.

[More on HMAC](/crypto/hashing/hmac)

## Store a password

```ts
import { argon2Hash, argon2Verify } from "unsecure/argon2";

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

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

The salt is generated for you and travels inside the string, so one text column is the whole storage format.

[More on password hashing](/crypto/password-hashing)

## Generate an identifier and a token

```ts
import { uuidv7, uuidv7Timestamp } from "unsecure/uuid";
import { secureGenerate } from "unsecure/generate";

const id = uuidv7();
// "01a076ba-1e53-7411-8518-84905f353e3d"

new Date(uuidv7Timestamp(id));
// the millisecond the id was made

secureGenerate({ length: 32, specials: false });
// "eO1k3t091l72uZTqhY050kEJ6vdB0j0V"
```

`uuidv7` sorts by creation time, which is what makes it a friendlier database key than `uuidv4`.

[More on UUIDs](/generate/uuid) · [More on generation](/generate/secrets/generate)

## Check a one-time password

```ts
import { generateOTPSecret, otpauthURI, totpVerify } from "unsecure/otp";

const secret = generateOTPSecret();
// a 32-character base32 string, 20 random bytes

otpauthURI({ type: "totp", secret, account: "user@example.com", issuer: "My App" });
// "otpauth://totp/My%20App:user%40example.com?secret=…&issuer=My%20App&algorithm=SHA1&digits=6&period=30"

await totpVerify(secret, "287082");
// { valid: false, delta: 0 }  — or { valid: true, delta: 0, step: 59623316 }
```

Render the URI as a QR code, store the secret, and check the six digits the app shows.

[More on one-time passwords](/crypto/otp)

## Next

- [Recipes](/examples) puts these together into whole tasks.
- [Errors](/safety/errors) is the one page to read before writing a `catch`.
