From 8ff8fed96b03e35ec3e69ea92874dd827315f3c8 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Wed, 18 Mar 2026 23:08:00 -0700 Subject: [PATCH] Update readme to reflect current API. Add node bundle to package definition. Document libsodium authorship. --- AUTHORS.md | 6 ++- README.md | 139 ++++++++++++++++++++++++++++++++++++--------------- package.json | 6 +-- 3 files changed, 107 insertions(+), 44 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index b73efa0..f53d78c 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -5,10 +5,14 @@ SPDX-License-Identifier: GPL-3.0-or-later # Authors -[nano-nacl](https://git.codecow.com/nano-nacl.git) +[nano-nacl](https://codecow.com/nano-nacl.git) - Chris Duncan (codecow.com) +[libsodium](https://github.com/jedisct1/libsodium/tree/d24faf56214469b354b01c8ba36257e04737101e) + +- Frank Denis (@jedisct1) + [tweetnacl-js](https://github.com/dchest/tweetnacl-js/tree/e6141a20553498697e9e7d92fbc4517994caff52) - Dmitry Chestnykh (@dchest) diff --git a/README.md b/README.md index bac4d98..4030ecd 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ SPDX-License-Identifier: GPL-3.0-or-later _Block signing and validation for Nano cryptocurrency using WebAssembly._ -NanoNaCl is an AssemblyScript port of tweetnacl-js, modified to hash using -BLAKE2b instead of SHA-512 as specified for Nano cryptocurrency. It can derive -public keys from private keys, sign blocks, and verify block signatures. All -processing takes place client-side and offline. +NanoNaCl is an AssemblyScript implementation of select Ed25519 functions used by +the Nano cryptocurrency. It is modified to hash using BLAKE2b instead of SHA-512 +and can derive public keys from private keys, sign blocks, and verify block +signatures. All processing takes place client-side and offline. For more information about the public key derivation algorithm used by Nano, see @@ -27,19 +27,9 @@ For more information about the block format defined for hashing and signing, see npm i nano-nacl ``` -## Usage - -### Import - -The easiest way to use NanoNaCl is to import it into your NodeJS project. - -```javascript -import { derive, sign, verify } from "nano-nacl"; -// OR -import * as NanoNaCl from "nano-nacl"; -``` +### Browser -You can also use it directly on a webpage with a script module: +NanoNaCl can be used directly on a webpage with a script module: ```html ``` +### NodeJS + +NanoNaCl can be imported into NodeJS projects: + +```javascript +import { derive, sign, verify } from "nano-nacl"; +``` + +## Usage + +Each function has a synchronous implementation which is preferable for speed. +These versions require Uint8Array byte arrays and return the same. + +If a non-blocking solution is required, asynchronous implementations are +provided which use Web Workers in the browser or Worker threads in NodeJS. These +versions require hex strings and return the same. + ### Derive ```javascript -// `sk` is a 64-char hex string secret key -const sk = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; +// `prv` is a 32-byte Uint8Array private key +const prv = new Uint8Array(32); +const pub = NanoNaCl.derive(prvBytes); +// `pub` is a 32-byte Uint8Array public key for a Nano account +``` + +### Derive (async) -const pk = await NanoNaCl.derive(sk); -// `pk` is a 64-char hex string public key for a Nano account +```javascript +// `prv` is a 64-character hex string private key +const prv = "0000000000000000000000000000000000000000000000000000000000000000"; +const pub = await NanoNaCl.deriveAsync(prv); +// `pub` is a 64-character hex string public key for a Nano account ``` ### Sign +```javascript +// `hash` is a 32-byte Uint8Array hash of a valid Nano transaction block +const hash = new Uint8Array(32); +// `prv` is a 32-byte Uint8Array private key +const prv = new Uint8Array(32); +// `pub` is a 32-byte Uint8Array public key derived from `prv` +const pub = NanoNaCl.derive(prv); +// `sk` is a 64-byte Uint8Array secret key joining private and public keys +const sk = new Uint8Array([...prv, ...pub]); + +const sig = NanoNaCl.sign(hash, sk); +// `sig` is a 64-byte Uint8Array signature for the block hash +``` + +### Sign (async) + ```javascript // `hash` is a 64-char hex string hash of a valid Nano transaction block const hash = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; -// `sk` is a 64-char hex string secret key -const sk = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; - -const sig = await NanoNaCl.sign(hash, sk); +// `prv` is a 64-char hex string private key +const prv = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; +// `pub` is a 64-char hex string public key derived from `prv` +const pub = await NanoNaCl.deriveAsync(prv); +// `sk` is a 128-char hex string secret key joining private and public keys +const sk = prv + pub; + +const sig = await NanoNaCl.signAsync(hash, sk); // `sig` is a 128-char hex string signature on the blockhash ``` ### Verify ```javascript -// `hash` is a 64-char hex string hash of a valid Nano transaction block -const hash = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; -// `sig` is a 128-char hex string signature on the blockhash +// `sig` is a 64-byte Uint8Array signature on a block hash +const sig = new Uint8Array(64); +// `hash` is a 32-byte Uint8Array hash of a valid Nano transaction block +const hash = new Uint8Array(32); +// `pub` is a 32-byte Uint8Array public key for a Nano account +const pub = new Uint8Array(32); + +const v = NanoNaCl.verify(sig, hash, pub); +// `v` is a boolean 'true' if the same `prv` that derives `pub` was also used to create `sig` by signing `hash`, else 'false' +``` + +### Verify (async) + +```javascript +// `sig` is a 128-char hex string signature on a block hash const sig = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; -// `pk` is a 64-char hex string public key for a Nano account -const pk = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; +// `hash` is a 64-char hex string hash of a valid Nano transaction block +const hash = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; +// `pub` is a 64-char hex string public key for a Nano account +const pub = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"; -const v = await NanoNaCl.verify(hash, sig, pk); -// `v` is a boolean 'true' if `pk` was used to sign `hash` with `sig`, else 'false' +const v = await NanoNaCl.verifyAsync(sig, hash, pub); +// `v` is a boolean 'true' if the same `prv` that derives `pub` was also used to create `sig` by signing `hash`, else 'false' ``` ## Notes -The tweetnacl-js implementation was selected as the basis for NanoNaCl due to -its historical reliability and security. For this project, it has been altered -to use BLAKE2b as its internal hashing algorithm instead of SHA-512. It has also -been optimized for Nano cryptocurrency needs, and many tweetnacl-js functions -have been removed due to the very narrow use case to which it is applied here. +The tweetnacl-js implementation was originally selected as the basis for +NanoNaCl due to its historical reliability and security. Over time, however, it +became clear that tweetnacl was designed to optimize size and not speed. Soon +after, libsodium became the reference from which functionality was ported. + +For this project, the internal hash mechanism was altered to use BLAKE2b +instead of SHA-512 so that it aligns with the Nano protocol. It has also been +optimized specifically for Nano needs; many functions have been modified or +removed due to the very narrow use case to which it is applied here. ## Tests A few basic tests are availabe in the source repository. -- `test/index.html` in the source repository contains a web interface to change - execution options and compare results. +- `index.html` is a web interface to test browser execution and compare + performance with other browser-based implementations. +- `test.mjs` is a basic test for NodeJS to check result validity. ## Building @@ -110,7 +164,7 @@ A few basic tests are availabe in the source repository. 1. Compile, minify, and bundle ```console -git clone https://git.codecow.com/nano-nacl.git +git clone https://codecow.com/nano-nacl.git cd nano-nacl npm i ``` @@ -126,7 +180,12 @@ See AUTHORS.md ## Licenses GNU GPL version 3 or later -tweetnacl-js is public domain under the Unlicense and was copied from the + +libsodium is distributed under the ISC license and was referenced from the +following commit hash: + + +tweetnacl-js is public domain under the Unlicense and was referenced from the following commit hash: diff --git a/package.json b/package.json index f8043ad..af8a7c4 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "coin", "wasm" ], - "homepage": "https://codecow.com", + "homepage": "https://git.codecow.com", "bugs": "bug-nano-nacl@codecow.com", "license": "(GPL-3.0-or-later AND MIT)", "author": "Chris Duncan ", @@ -22,7 +22,6 @@ }, "files": [ "/dist", - "/docs", "/LICENSES", "AUTHORS.md", "package.json.license" @@ -35,7 +34,7 @@ }, "repository": { "type": "git", - "url": "git+https://git.codecow.com/nano-nacl.git" + "url": "git+https://codecow.com/nano-nacl.git" }, "scripts": { "build": "npm run clean && npm run compile && node ./esbuild/dev.mjs", @@ -56,6 +55,7 @@ "exports": { ".": { "types": "./dist/index.d.ts", + "node": "./dist/node.js", "default": "./dist/browser.js" } }, -- 2.47.3