From: Chris Duncan Date: Sun, 15 Feb 2026 23:50:27 +0000 (-0800) Subject: Add layer of abstraction to wasm functions. X-Git-Tag: v1.0.0~23 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=af11223a0e9b2f5f77bccaf2eef8400289d15df9;p=nano25519.git Add layer of abstraction to wasm functions. --- diff --git a/assembly/nano-nacl.ts b/assembly/nano-nacl.ts index f7691ef..592498c 100644 --- a/assembly/nano-nacl.ts +++ b/assembly/nano-nacl.ts @@ -650,7 +650,8 @@ export function derive (k0: u64, k1: u64, k2: u64, k3: u64): Uint8Array { } /** -* Signs the message using the private key and returns a signature. +* Signs the message using the private key and returns a signature. This mirrors +* the functionality of `nacl.sign.detached()`. * * @param {Uint8Array} message - Message to sign * @param {Uint8Array} privateKey - 32-byte key to use for signing @@ -677,14 +678,15 @@ export function sign (h0: u64, h1: u64, h2: u64, h3: u64, k0: u64, k1: u64, k2: } /** -* Verifies a signature on a blockhash against a public key. +* Verifies a signature on a blockhash against a public key. This mirrors the +* functionality of `nacl.sign.detached.verify()`. * * @param {Uint8Array} blockhash - 32-byte hash of signed Nano block * @param {Uint8Array} signature - 64-byte signature * @param {Uint8Array} publicKey - 32-byte key used for signing * @returns {boolean} - True if `publicKey` was used to sign `blockhash` and generate `signature`, else false */ -export function verify (h0: u64, h1: u64, h2: u64, h3: u64, s0: u64, s1: u64, s2: u64, s3: u64, s4: u64, s5: u64, s6: u64, s7: u64, k0: u64, k1: u64, k2: u64, k3: u64): boolean { +export function verify (h0: u64, h1: u64, h2: u64, h3: u64, s0: u64, s1: u64, s2: u64, s3: u64, s4: u64, s5: u64, s6: u64, s7: u64, k0: u64, k1: u64, k2: u64, k3: u64): i32 { const h = new Uint64Array(4); h.set([h0, h1, h2, h3]) const s = new Uint64Array(8); s.set([s0, s1, s2, s3, s4, s5, s6, s7]) const k = new Uint64Array(4); k.set([k0, k1, k2, k3]) diff --git a/index.ts b/index.ts index 735ab3e..d58f854 100644 --- a/index.ts +++ b/index.ts @@ -2,9 +2,9 @@ //! SPDX-License-Identifier: GPL-3.0-or-later import nacl from './build/nano-nacl.wasm' -type Derive = (k0: bigint, k1: bigint, k2: bigint, k3: bigint) => Uint8Array -type Sign = (h0: bigint, h1: bigint, h2: bigint, h3: bigint, k0: bigint, k1: bigint, k2: bigint, k3: bigint) => Uint8Array -type Verify = (h0: bigint, h1: bigint, h2: bigint, h3: bigint, s0: bigint, s1: bigint, s2: bigint, s3: bigint, s4: bigint, s5: bigint, s6: bigint, s7: bigint, k0: bigint, k1: bigint, k2: bigint, k3: bigint) => boolean +type Derive = (k0: bigint, k1: bigint, k2: bigint, k3: bigint) => number +type Sign = (h0: bigint, h1: bigint, h2: bigint, h3: bigint, k0: bigint, k1: bigint, k2: bigint, k3: bigint) => number +type Verify = (h0: bigint, h1: bigint, h2: bigint, h3: bigint, s0: bigint, s1: bigint, s2: bigint, s3: bigint, s4: bigint, s5: bigint, s6: bigint, s7: bigint, k0: bigint, k1: bigint, k2: bigint, k3: bigint) => number type Data = { action: string hash?: string @@ -18,10 +18,10 @@ const NanoNaCl = async (bytes: number[]): Promise => { let wasm let module let instance + let derive: (k: BigUint64Array) => Uint8Array + let sign: (h: BigUint64Array, k: BigUint64Array) => Uint8Array + let verify: (h: BigUint64Array, s: BigUint64Array, k: BigUint64Array) => boolean let memory: WebAssembly.Memory - let derive: Derive - let sign: Sign - let verify: Verify async function setup (): Promise { try { @@ -44,10 +44,8 @@ const NanoNaCl = async (bytes: number[]): Promise => { memory: new WebAssembly.Memory({ initial: 256, maximum: 1024 }) } }) - const { exports } = instance as any - derive = exports.derive - verify = exports.verify - memory = instance.exports.memory as WebAssembly.Memory + const { exports } = instance as { exports: { derive: Derive, sign: Sign, verify: Verify, memory: WebAssembly.Memory } } + memory = exports.memory function __liftString (pointer: number) { if (!pointer) return null const @@ -70,28 +68,50 @@ const NanoNaCl = async (bytes: number[]): Promise => { return new Uint8Array(memory.buffer, offset, length).slice() } - derive = function (k0, k1, k2, k3) { + derive = function (k: BigUint64Array): Uint8Array { // assembly/nano-nacl/derive(u64, u64, u64, u64) => ~lib/typedarray/Uint8Array - k0 = k0 || 0n - k1 = k1 || 0n - k2 = k2 || 0n - k3 = k3 || 0n + const k0 = k[0] ?? 0n + const k1 = k[1] ?? 0n + const k2 = k[2] ?? 0n + const k3 = k[3] ?? 0n return __liftTypedArray(exports.derive(k0, k1, k2, k3) >>> 0) } - sign = function (h0, h1, h2, h3, k0, k1, k2, k3) { + sign = function (h: BigUint64Array, k: BigUint64Array): Uint8Array { // assembly/nano-nacl/sign(u64, u64, u64, u64, u64, u64, u64, u64) => ~lib/typedarray/Uint8Array - h0 = h0 || 0n - h1 = h1 || 0n - h2 = h2 || 0n - h3 = h3 || 0n - k0 = k0 || 0n - k1 = k1 || 0n - k2 = k2 || 0n - k3 = k3 || 0n + const h0 = h[0] ?? 0n + const h1 = h[1] ?? 0n + const h2 = h[2] ?? 0n + const h3 = h[3] ?? 0n + const k0 = k[0] ?? 0n + const k1 = k[1] ?? 0n + const k2 = k[2] ?? 0n + const k3 = k[3] ?? 0n return __liftTypedArray(exports.sign(h0, h1, h2, h3, k0, k1, k2, k3) >>> 0) } + verify = function (h: BigUint64Array, s: BigUint64Array, k: BigUint64Array): boolean { + // assembly/nano-nacl/sign(u64, u64, u64, u64, u64, u64, u64, u64) => ~lib/typedarray/Uint8Array + const h0 = h[0] || 0n + const h1 = h[1] || 0n + const h2 = h[2] || 0n + const h3 = h[3] || 0n + const s0 = s[0] || 0n + const s1 = s[1] || 0n + const s2 = s[2] || 0n + const s3 = s[3] || 0n + const s4 = s[4] || 0n + const s5 = s[5] || 0n + const s6 = s[6] || 0n + const s7 = s[7] || 0n + const k0 = k[0] || 0n + const k1 = k[1] || 0n + const k2 = k[2] || 0n + const k3 = k[3] || 0n + const result = exports.verify(h0, h1, h2, h3, s0, s1, s2, s3, s4, s5, s6, s7, k0, k1, k2, k3) + return result === 1 + } + isReady = true } catch (err) { throw new Error('Error instantiating WebAssembly', { cause: err }) @@ -107,9 +127,9 @@ const NanoNaCl = async (bytes: number[]): Promise => { const privateKeyArray = new BigUint64Array(4) const privateKeyView = new DataView(privateKeyArray.buffer) const publicKeyArray = new BigUint64Array(4) - const publicKeyView = new DataView(privateKeyArray.buffer) - const signatureArray = new BigUint64Array(4) - const signatureView = new DataView(privateKeyArray.buffer) + const publicKeyView = new DataView(publicKeyArray.buffer) + const signatureArray = new BigUint64Array(8) + const signatureView = new DataView(signatureArray.buffer) if (msg.data === 'start') { result = 'started' @@ -128,7 +148,7 @@ const NanoNaCl = async (bytes: number[]): Promise => { const u64 = privateKey.slice(i, i + 16) privateKeyView.setBigUint64(i / 2, BigInt(`0x${u64}`)) } - const publicKey = derive(privateKeyArray[0], privateKeyArray[1], privateKeyArray[2], privateKeyArray[3]) + const publicKey = derive(privateKeyArray) if (publicKey == null) { throw new TypeError('Invalid verification response from WASM') } @@ -149,7 +169,7 @@ const NanoNaCl = async (bytes: number[]): Promise => { const u64 = privateKey.slice(i, i + 16) privateKeyView.setBigUint64(i / 2, BigInt(`0x${u64}`)) } - const signature = sign(hashArray[0], hashArray[1], hashArray[2], hashArray[3], privateKeyArray[0], privateKeyArray[1], privateKeyArray[2], privateKeyArray[3]) + const signature = sign(hashArray, privateKeyArray) if (signature == null) { throw new TypeError('Invalid signature from WASM') } @@ -170,15 +190,15 @@ const NanoNaCl = async (bytes: number[]): Promise => { const u64 = hash.slice(i, i + 16) hashView.setBigUint64(i / 2, BigInt(`0x${u64}`)) } - for (let i = 0; i < publicKey.length; i += 16) { - const u64 = publicKey.slice(i, i + 16) - publicKeyView.setBigUint64(i / 2, BigInt(`0x${u64}`)) - } for (let i = 0; i < signature.length; i += 16) { const u64 = signature.slice(i, i + 16) signatureView.setBigUint64(i / 2, BigInt(`0x${u64}`)) } - const isVerified = verify(hashArray[0], hashArray[1], hashArray[2], hashArray[3], signatureArray[0], signatureArray[1], signatureArray[2], signatureArray[3], signatureArray[4], signatureArray[5], signatureArray[6], signatureArray[7], publicKeyArray[0], publicKeyArray[1], publicKeyArray[2], publicKeyArray[3]) + for (let i = 0; i < publicKey.length; i += 16) { + const u64 = publicKey.slice(i, i + 16) + publicKeyView.setBigUint64(i / 2, BigInt(`0x${u64}`)) + } + const isVerified = verify(hashArray, signatureArray, publicKeyArray) if (isVerified == null) { throw new TypeError('Invalid verification response from WASM') }