yescrypt-wasm
Version:
WebAssembly module for Yescrypt
120 lines (80 loc) • 4.26 kB
Markdown
# Yescrypt WebAssembly Module
[](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)