# Yescrypt WebAssembly Module

[![NPM Version](https://img.shields.io/npm/v/yescrypt-wasm)](https://www.npmjs.com/package/yescrypt-wasm)

Yescrypt / Scrypt WebAssembly Module for Browsers / Node.js

## Prerequisites

* Node.js LTS or Browser where WebAssembly is enabled

## Install

```bash
$ yarn add yescrypt-wasm
```

or on html header / body

```html
<script src="https://cdn.jsdelivr.net/npm/yescrypt-wasm/lib/yescrypt.umd.min.js"></script>
```

WASM file is fully embedded on script so that you need to load nothing (and should work with any bundlers without hassle)

## Build WASM (optional)

Requires latest [Emscripten](https://emscripten.org/docs/getting_started/downloads.html) WASM compiler

```bash
$ yarn && yarn build:wasm
```

Will update .wasm and bundled files

## Build library (optional)

Rebuild node.js and web umd bundle files

```bash
$ yarn && yarn build

```

## Example Code

```js
import { Yescrypt, bytesToHex } from './lib/index.js';

const getRandomHex = () => Buffer.from(crypto.getRandomValues(new Uint8Array(32)));

async function test() {
    const yescrypt = await Yescrypt.init();

    const passwd = Buffer.from("7000000001e980924e4e1109230383e66d62945ff8e749903bea4336755c00000000000051928aff1b4d72416173a8c3948159a09a73ac3bb556aa6bfbcad1a85da7f4c1d13350531e24031b939b9e2b", "hex");

    console.log(bytesToHex(yescrypt.yescrypt_kdf(passwd, getRandomHex())))
}

test();
```

Also refer `example.html` for example of using it on browser.

## API

All four methods take the password and salt as `Uint8Array`/`Buffer` and honor
the explicit byte length (binary-safe — a password containing or sized past a NUL
byte is hashed correctly):

```ts
yescrypt.scrypt_kdf  (passwd, salt, N?, r?, p?, t?, flags?, g?, dklen?): Uint8Array
yescrypt.yescrypt_kdf(passwd, salt, N?, r?, p?, t?, flags?, g?, dklen?): Uint8Array
yescrypt.scrypt_hash (passwd, salt, N?, r?, p?, t?, flags?, g?): string  // "$y$..." crypt(3) form
yescrypt.yescrypt_hash(passwd, salt, N?, r?, p?, t?, flags?, g?): string
```

These map directly onto the C `yescrypt_params_t` (`yescrypt-c/yescrypt.h`):

| param   | meaning                                   | default (`scrypt_*` / `yescrypt_*`) |
|---------|-------------------------------------------|-------------------------------------|
| `N`     | cost (power of two)                       | `4096`                              |
| `r`     | block size                                | `32`                                |
| `p`     | parallelism                               | `1`                                 |
| `t`     | extra time without extra memory           | `0`                                 |
| `flags` | mode/flavor (see `YESCRYPT_*` constants)  | `0` / `YESCRYPT_DEFAULTS`           |
| `g`     | hash-upgrade count                        | `0`                                 |
| `dklen` | output length in bytes (`*_kdf` only)     | `64`                                |

Flag constants are exported (`YESCRYPT_WORM`, `YESCRYPT_RW`, `YESCRYPT_DEFAULTS`,
the `YESCRYPT_ROUNDS_*` / `GATHER_*` / `SIMPLE_*` / `SBOX_*` family) and may be
OR'ed together to match any C-side configuration. ROM (`NROM` / shared) is not
yet exposed.

Invalid parameters throw a `RangeError` (`N` must be a power of two `> 1`,
`r * p < 2^30`), and a genuine hashing failure throws an `Error` rather than
returning a zeroed/empty result. The WASM module is built with
`ALLOW_MEMORY_GROWTH`, so larger `N`/`r` no longer abort the whole instance —
they either succeed or surface an out-of-memory `Error`.

```js
import { Yescrypt, YESCRYPT_DEFAULTS, YESCRYPT_WORM } from './lib/index.js';

const y = await Yescrypt.init();
const passwd = Buffer.from('a'.repeat(20));            // 20-byte password works correctly
const salt = Buffer.from(crypto.getRandomValues(new Uint8Array(16)));

// crypt(3)-style encoded hash for /etc/shadow (yescrypt defaults):
console.log(y.yescrypt_hash(passwd, salt));

// raw 32-byte KDF output with custom flags:
console.log(y.yescrypt_kdf(passwd, salt, 4096, 32, 1, 0, YESCRYPT_DEFAULTS, 0, 32));
```

## References

[Yescrypt](https://github.com/openwall/yescrypt)

[scrypt-js](https://github.com/ricmoo/scrypt-js)

[scrypt-wasm](https://github.com/MyEtherWallet/scrypt-wasm)