npm.io
5.36.0 β€’ Published 16h ago

zenroom

Licence
AGPL-3.0-only
Version
5.36.0
Deps
0
Size
10.1 MB
Vulns
0
Weekly
0
Stars
247

Zenroom js bindings

Zenroom js bindings provides a javascript wrapper of Zenroom, a secure and small virtual machine for crypto language processing.

Zenroom

npm Dyne.org




Install

Stable releases are published on https://www.npmjs.com/package/zenroom that have a slow pace release schedule that you can install with

npm install zenroom
# or using yarn
yarn add zenroom
# or using pnpm
pnpm add zenroom
# or using bun
bun add zenroom

Usage

The bindings are composed of two main functions:

  • zencode_exec to execute Zencode. To learn more about zencode syntax look here
  • zenroom_exec to execute our special flavor of Lua enhanced with Zenroom's special effects

Both of this functions accepts a mandatory SCRIPT to be executed and some optional parameters:

  • DATA
  • KEYS
  • EXTRA
  • CONTEXT
  • CONF

All in form of strings. This means that if you want to pass a JSON you have to JSON.stringify it before.

Both functions return a Promise.

To start using the zenroom vm just

import { zenroom_exec, zencode_exec, introspection } from "zenroom";
// or if you don't use >ES6
// const { zenroom_exec, zencode_exec } = require('zenroom')

// Zencode: generate a random array. This script takes no extra input

const zencodeRandom = `
  Given nothing
  When I create the random array with '16' elements each of '32' bits
  Then print all data
`;

zencode_exec(zencodeRandom)
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

// Zencode: encrypt a message.
// This script takes the options' object as the second parameter: you can include data and/or keys as input.
// The "config" parameter is also optional.

const zencodeEncrypt = `
  Scenario 'ecdh': Encrypt a message with the password
  Given that I have a 'string' named 'password'
  Given that I have a 'string' named 'message'
  Given that I have a 'string' named 'extra'
  When I append 'extra' to 'message'
  When I encrypt the secret message 'message' with 'password'
  Then print the 'secret message'`;

const zenKeys = `
  {
    "password": "myVerySecretPassword"
  }
`;

const zenData = `
  {
      "message": "HELLO WORLD"
  }
`;

const zenExtra = `
  {
      "extra": "!!!"
  }
`;

zencode_exec(zencodeEncrypt, {
  data: zenData,
  keys: zenKeys,
  extra: zenExtra,
  conf: `debug=1`,
})
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

// Lua Hello World!

const lua = `print("Hello World!")`;
zenroom_exec(lua)
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

// to pass the optional parameters you pass an object literal eg.

try {
  const result = await zenroom_exec(`print(DATA..KEYS..EXTRA..CONTEXT)`, {
    data: "Hello ",
    keys: "from ",
    extra: "Zenroom ",
    context: "developers",
    conf: `debug=1`,
  });
  console.log(result); // => Hello from Zenroom developers
} catch (e) {
  console.error(e);
}

// code inspection is done via the `zencode_valid_input` primitive function or by a utility `introspect`

const introspection = await introspection(
  `Given I have a 'string' named 'missing'
  Then print the codec`
);
console.log(introspection); // => an object described as https://dev.zenroom.org/#/pages/how-to-embed?id=input-validation

Direct primitives (hex API)

Zenroom also exports direct cryptographic primitives that work without writing Lua or Zencode scripts. All binary inputs and outputs use lowercase hex strings.

One-shot hash
import { hashHex, utf8ToHex } from "zenroom";

const { result: sha256 } = await hashHex("sha256", utf8ToHex("hello"));
console.log(sha256);
// => 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Supported algorithms: sha256, sha384, sha512, sha3_256, sha3_512, shake256, keccak256, ripemd160.

PBKDF2 key derivation
import { pbkdf2Hex } from "zenroom";

const { result: key } = await pbkdf2Hex(
  "sha256",
  utf8ToHex("password"),
  utf8ToHex("salt"),
  4096,
  32
);
// key is a 64-char hex string (32 bytes)
EdDSA signatures
import { signKeygenHex, signPubgenHex, signCreateHex, signVerifyHex } from "zenroom";

// Generate a secret key (optionally pass a hex rngseed)
const { result: sk } = await signKeygenHex("eddsa");

// Derive the public key
const { result: pk } = await signPubgenHex("eddsa", sk);

// Sign a hex-encoded message
const { result: sig } = await signCreateHex("eddsa", sk, utf8ToHex("hello"));

// Verify the signature
const { result: ok } = await signVerifyHex("eddsa", pk, utf8ToHex("hello"), sig);
console.log(ok); // => 1
Merkle tree recipes (Lua-backed)
import { merkleRootHex } from "zenroom";

const { result: root } = await merkleRootHex(
  ["0101010101010101010101010101010101010101010101010101010101010101",
   "0202020202020202020202020202020202020202020202020202020202020202"],
  "sha256"
);
console.log(root); // hex-encoded merkle root
Named recipes
import { recipeExec } from "zenroom";

const { result } = await recipeExec("merkle.root", JSON.stringify({
  hash: "sha256",
  leaves: [
    "0101010101010101010101010101010101010101010101010101010101010101",
    "0202020202020202020202020202020202020202020202020202020202020202",
  ],
}));
const { root } = JSON.parse(result);
Encoding helpers
import { bytesToHex, hexToBytes, utf8ToHex, hexToUtf8 } from "zenroom";

const hex = utf8ToHex("hello");          // "68656c6c6f"
const str = hexToUtf8("68656c6c6f");     // "hello"

const bytes = hexToBytes("deadbeef");    // Uint8Array [0xde, 0xad, 0xbe, 0xef]
const back  = bytesToHex(bytes);         // "deadbeef"
Streaming hash (legacy API)
import { zenroom_hash } from "zenroom";

const { result: digest } = await zenroom_hash("sha256", "hello world");
// digest is base64-encoded (legacy format)

This legacy API now emits a deprecation warning on stderr (logs).

For large inputs or one-shot hashing with hex output, prefer hashHex which handles chunking internally and returns lowercase hex.


## 😍 Acknowledgements

Copyright (C) 2018-2026 by [Dyne.org](https://www.dyne.org) foundation, Amsterdam

Designed, written and maintained by Puria Nafisi Azizi.

<img src="https://upload.wikimedia.org/wikipedia/commons/8/84/European_Commission.svg" class="pic" alt="Project funded by the European Commission">

This project is receiving funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement nr. 732546 (DECODE).

---

## πŸ‘€ Contributing

Please first take a look at the [Dyne.org - Contributor License Agreement](CONTRIBUTING.md) then

1.  [FORK IT](https://github.com/puria/zenroomjs/fork)
2.  Create your feature branch `git checkout -b feature/branch`
3.  Commit your changes `git commit -am 'Add some fooBar'`
4.  Push to the branch `git push origin feature/branch`
5.  Create a new Pull Request
6.  Thank you

---

## πŸ’Ό License

      Zenroom js - a javascript wrapper of zenroom
      Copyright (c) 2018-2026 Dyne.org foundation, Amsterdam

      This program is free software: you can redistribute it and/or modify
      it under the terms of the GNU Affero General Public License as
      published by the Free Software Foundation, either version 3 of the
      License, or (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU Affero General Public License for more details.

      You should have received a copy of the GNU Affero General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.

Keywords