---
title: "Getting Started"
description: "Install the package and hash one string. Every algorithm answers with the same result shape"
canonical_url: "https://hashes.agntn.dev/guide"
---
# Getting Started

> Install the package and hash one string. Every algorithm answers with the same result shape

<warning title="Pre-1.0">

The API and the tool list can still move. Pin exact versions if you build on it now.

</warning>

<caution title="Not audited">

This code has never had a security audit. Do not use it in production, with real funds or with sensitive data. It is meant for agents, puzzles and local experiments only. It comes as is, without warranty of any kind, and the authors are not liable for any loss, as the MIT license states. Anything that matters wants an audited library.

</caution>

## Why this exists

Ask a model for the SHA-256 of a string. It gives you 64 hex characters, very confidently, and they're wrong. Hashing is the one thing a language model can't fake, so it should call something that actually hashes. `@agntn/hashes` is that something, and it's the same thing in your TypeScript and in your terminal.

It also has the hashes chains quietly depend on. Keccak-256 with its pre-SHA-3 padding, HASH160, double SHA-256, BLAKE2b cut to 32 or 28 bytes, SHA-512Half. Those are the ones people get subtly wrong, and subtly wrong means a different address.

No HTTP, no keys, no telemetry, no hashing dependency. Every digest is plain TypeScript in `src/core/`, and the library imports nothing from `node:*`. That's why this site can run it in your browser.

## Install

```bash
pnpm add @agntn/hashes
```

Node.js 26 or newer. It needs `Uint8Array` with native hex and base64, and 26 is where that stopped being a question.

## First call

```ts [first.ts]
import { create } from "@agntn/hashes";

const result = create("sha256").hash("abc");
result.digest; // "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
result.digestLength; // 32
```

`create(name)` wants the exact registry key and hands back one cached instance. `resolveAlgorithm("SHA-256")` forgives case and punctuation and takes the label too, then wants an exact match. No prefixes, no fuzzy guess. A typo is an `UnknownAlgorithmError`, and its message lists every name that does exist. Half a name gets only what it could have meant: `sha3` names `sha3-256` and `sha3-512`.

## The shape

Every `hash()` returns this, whatever the algorithm:

```ts
interface HashResult {
  digest: string | Uint8Array; // bytes only with encoding "binary"
  algorithm: string; // "sha256"
  operation: "hash" | "hmac";
  encoding: "hex" | "base64" | "base64url" | "binary";
  digestLength: number; // bytes of the raw digest
  options: Record<string, unknown>; // what the digest depends on: encoding, salt, cost, seed
}
```

`options` is the part people skip and then regret. For scrypt it holds the salt it drew and the cost it ran with, and without those the digest is a string that looks random and that you can never reproduce.

## What ships

<algorithm-roster>



</algorithm-roster>

Every row comes from `create(name).info()`, read in your browser. The HMAC column says which ones take a `key`. The rest refuse it with an error, they don't quietly hash without it.

## Errors

```ts
import { HashError, InvalidOptionError, UnknownAlgorithmError, create } from "@agntn/hashes";

try {
  create("scrypt").hash("password", { N: 1000 });
} catch (error) {
  if (error instanceof InvalidOptionError) {
    error.option; // "N"
    error.reason; // "must be a power of 2 and >= 2"
  }
}
```

A name nobody registered is an `UnknownAlgorithmError`. A bad value is an `InvalidOptionError` with the option, the value and the reason. A required one left out is a `MissingOptionError`. Anything else an algorithm throws gets wrapped by `normalizeError` into a `HashError` that names the algorithm. The CLI prints the message on one line and exits 1. No stack trace, the input was wrong, not you.

## Next

- [Hashing](https://hashes.agntn.dev/guide/hashing): encodings, text versus bytes, names.
- [HMAC and verify](https://hashes.agntn.dev/guide/verify): keys, and comparing digests without a timing leak.
- [Salted KDFs](https://hashes.agntn.dev/guide/kdf): scrypt and PBKDF2, and why they print the salt.
- [Length extension](https://hashes.agntn.dev/guide/extend): sign a longer message without the secret.
- [Identify a hash](https://hashes.agntn.dev/guide/identify): which algorithms a digest may come from.
- [Search for a transform](https://hashes.agntn.dev/guide/search): which words, joined and hashed how, give a digest.
- [CLI](https://hashes.agntn.dev/guide/cli): the `hashes` command.
- [Agents](https://hashes.agntn.dev/guide/agents): the same tools over MCP, local or remote, Pi, OMP and the AI SDK.
- [Custom algorithms](https://hashes.agntn.dev/guide/custom): extend `FixedHash`, register it.
- [Playground](https://hashes.agntn.dev/playground): every algorithm, in the page.


## Sitemap

See the full [sitemap](https://hashes.agntn.dev/sitemap.md) for all pages.
