Update integration and input guidance in README.
Emit declarations to types directory. Use esbuild to copy specific type definitions. Move implementation file and delete duplicated exports. Expand on test vector authorship. Include unlicense for tweetnacl origins.
[Poly1305-donna](https://github.com/floodyberry/poly1305-donna)
- Andrew Moon (@floodyberry)
+
+[python-ed25519-blake2b](https://github.com/Matoking/python-ed25519-blake2b)
+
+- Janne Pulkkinen (@Matoking)
--- /dev/null
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
+
+In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
nano25519 can be imported into NodeJS projects:
```javascript
-import { derive, sign, verify } from "nano25519";
+import * as nano25519 from "nano25519";
+```
+
+Sync and async modules can be imported separately depending on requirements.
+
+```javascript
+import { derive, sign, verify } from "nano25519/sync";
+import { deriveAsync, signAsync, verifyAsync } from "nano25519/async";
```
## 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.
+provided which use Web Workers in the browser or Worker threads in NodeJS.
+
+Inputs can be passed as Uint8Array byte arrays (preferable) or strings. The
+output will return the same type as the input.
### Derive
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.
+optimized to take advantage of SIMD parallelism using WebAssembly vector types.
## Tests
- `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.
+- `test.mjs` is a test for NodeJS to check result validity. It runs a
+ derive-sign-verify sequence for public test vectors obtained from the
+ python-ed25519-blake2b library.
## Building
const commonOptions = {
bundle: true,
loader: {
- '.wasm': 'binary'
+ '.wasm': 'binary',
+ '.d.ts': 'copy'
},
format: 'esm',
legalComments: 'inline',
outdir: 'dist',
}
-/**
- * @type {import('esbuild').BuildOptions}
- */
-export const prodOptions = {
- drop: ['console', 'debugger'],
- minify: true,
- sourcemap: false
-}
-
/**
* @type import("esbuild").BuildOptions
*/
platform: 'node',
target: 'node22',
entryPoints: [
- { in: './src/index.ts', out: 'index' },
- { in: './src/async.ts', out: 'async' },
- { in: './src/sync.ts', out: 'sync' }
+ { in: './src/*.ts', out: '' },
+ // { in: './src/async.ts', out: 'async' },
+ // { in: './src/sync.ts', out: 'sync' },
+ { in: './types/index.d.ts', out: 'index.d' },
+ { in: './types/async.d.ts', out: 'async.d' },
+ { in: './types/sync.d.ts', out: 'sync.d' }
],
packages: 'external',
dropLabels: ['BROWSER']
//! SPDX-License-Identifier: GPL-3.0-or-later
import { build } from 'esbuild'
-import { browserOptions, nodeOptions, prodOptions } from './config.mjs'
+import { browserOptions, nodeOptions } from './config.mjs'
+
+/**
+ * @type {import('esbuild').BuildOptions}
+ */
+export const prodOptions = {
+ drop: ['console', 'debugger'],
+ minify: true,
+ sourcemap: false
+}
await build({ ...browserOptions, ...prodOptions })
await build({ ...nodeOptions, ...prodOptions })
"scripts": {
"build": "npm run clean && npm run compile && node ./esbuild/dev.mjs",
"build:prod": "npm run clean && npm run compile && node ./esbuild/prod.mjs",
- "clean": "rm -rf {build,dist}",
+ "clean": "rm -rf {build,dist,types}",
"compile": "asc ./src/assembly/index.ts && tsc",
"prepublishOnly": "npm run test:prod",
"test": "npm run build && node ./test.mjs",
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { run } from './nano25519'
+import { run } from './lib/nano25519'
/**
* Asynchronous Nano public key derivation using WebAssembly.
import { Worker as NodeWorker } from 'node:worker_threads'
//@ts-expect-error
-import nano25519_wasm from '../build/nano25519.wasm'
+import nano25519_wasm from '../../build/nano25519.wasm'
type Data = {
action: string
}
}
}
-
-/**
- * Asynchronous Nano public key derivation using WebAssembly.
- * @param {Uint8Array<ArrayBuffer>} k - 64-character private key hex string
- * @returns Promise for 64-character public key hex string
- */
-export async function deriveAsync (privateKey: Uint8Array<ArrayBuffer>): Promise<Uint8Array<ArrayBuffer>>
-/**
- * Asynchronous Nano public key derivation using WebAssembly.
- * @param {string} k - 64-character private key hex string
- * @returns Promise for 64-character public key hex string
- */
-export async function deriveAsync (privateKey: string): Promise<string>
-export async function deriveAsync (privateKey: string | Uint8Array<ArrayBuffer>): Promise<string | Uint8Array<ArrayBuffer>> {
- return run({ action: 'derive', privateKey })
-}
-
-/**
- * Asynchronous signing using WebAssembly. To sign Nano blocks, the message
- * should be a 64-character block hash.
- * @param {Uint8Array<ArrayBuffer>} m - Variable-length message hex string up to 65536 characters
- * @param {Uint8Array<ArrayBuffer>} k - 128-character secret key (prv + pub) hex string
- * @returns Promise for 128-character detached signature hex string
- */
-export async function signAsync (message: Uint8Array<ArrayBuffer>, secretKey: Uint8Array<ArrayBuffer>): Promise<Uint8Array<ArrayBuffer>>
-/**
- * Asynchronous signing using WebAssembly. To sign Nano blocks, the message
- * should be a 64-character block hash.
- * @param {Uint8Array<ArrayBuffer>} m - Variable-length message hex string up to 65536 characters
- * @param {Uint8Array<ArrayBuffer>} k - 128-character secret key (prv + pub) hex string
- * @returns Promise for 128-character detached signature hex string
- */
-export async function signAsync (message: string, secretKey: string): Promise<string>
-export async function signAsync (message: string | Uint8Array<ArrayBuffer>, secretKey: string | Uint8Array<ArrayBuffer>): Promise<string | Uint8Array<ArrayBuffer>> {
- return run({ action: 'sign', message, secretKey })
-}
-
-/**
- * Asynchronous signature verification using WebAssembly. To verify Nano block
- * signatures, the message should be a 64-character block hash.
- * @param {Uint8Array<ArrayBuffer>} s - 128-character detached signature hex string
- * @param {Uint8Array<ArrayBuffer>} m - Variable-length message hex string to up 65536 characters
- * @param {Uint8Array<ArrayBuffer>} k - 64-character public key hex string
- * @returns Promise resolving to true if signature matches block hash and public key, else false
- */
-export async function verifyAsync (signature: Uint8Array<ArrayBuffer>, message: Uint8Array<ArrayBuffer>, publicKey: Uint8Array<ArrayBuffer>): Promise<boolean>
-/**
- * Asynchronous signature verification using WebAssembly. To verify Nano block
- * signatures, the message should be a 64-character block hash.
- * @param {Uint8Array<ArrayBuffer>} s - 128-character detached signature hex string
- * @param {Uint8Array<ArrayBuffer>} m - Variable-length message hex string to up 65536 characters
- * @param {Uint8Array<ArrayBuffer>} k - 64-character public key hex string
- * @returns Promise resolving to true if signature matches block hash and public key, else false
- */
-export async function verifyAsync (signature: string, message: string, publicKey: string): Promise<boolean>
-export async function verifyAsync (signature: string | Uint8Array<ArrayBuffer>, message: string | Uint8Array<ArrayBuffer>, publicKey: string | Uint8Array<ArrayBuffer>): Promise<boolean> {
- return !!(await run({ action: 'verify', signature, message, publicKey }))
-}
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { nano25519 } from "./nano25519"
+import { nano25519 } from "./lib/nano25519"
/**
* Nano public key derivation using WebAssembly.
"strict": true,
"declaration": true,
"emitDeclarationOnly": true,
- "outDir": "dist",
+ "outDir": "types",
"declarationMap": true,
"lib": [
"DOM",
],
"exclude": [
"assembly",
+ "build",
"dist"
]
}
badSignature: '74BCC59DBA39A1E34A5F75F96D6DE9154E3477AAD7DE30EA563DFCFE501A804215d484f5f757b4b7a9f4fcb2057fa423f76732c3a74b0fec5b0dd67b574a5910'
}
-// https://github.com/Matoking/python-ed25519-blake2b/blob/master/kat-ed25519-blake2b.txt
+/**
+ * Test vectors derived from "python-ed25519-blake2b" by Janne Pulkkinen.
+ * https://github.com/Matoking/python-ed25519-blake2b
+ */
export const PYTHON_ED25519_BLAKE2B_VECTORS = [
{
privateKey: '9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60',