From 766453e0777c3fa9aa0b2a65243aee57c206755e Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Sun, 15 Feb 2026 14:41:57 -0800 Subject: [PATCH] Rename NaCl input constants. Fix parameters and argument parsing for derive and verify functions. --- assembly/nano-nacl.ts | 76 +++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/assembly/nano-nacl.ts b/assembly/nano-nacl.ts index c0245e9..f7691ef 100644 --- a/assembly/nano-nacl.ts +++ b/assembly/nano-nacl.ts @@ -182,10 +182,10 @@ class Blake2b { } } -const crypto_sign_BYTES: u8 = 64 -const crypto_sign_PUBLICKEYBYTES: u8 = 32 -const crypto_sign_PRIVATEKEYBYTES: u8 = 32 -const crypto_sign_SEEDBYTES: u8 = 32 +const BLOCKHASH_BYTES: u8 = 32 +const PRIVATEKEY_BYTES: u8 = 32 +const PUBLICKEY_BYTES: u8 = 32 +const SIGNATURE_BYTES: u8 = 64 const D: Int64Array = new Int64Array(16); D.set([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]) const D2: Int64Array = new Int64Array(16); D2.set([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]) const X: Int64Array = new Int64Array(16); X.set([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]) @@ -621,33 +621,36 @@ function crypto_sign_open (m: Uint8Array, sm: Uint8Array, n: i32, pk: Uint8Array } /** -* Derives a public key from a private key "seed". +* Derives a Nano public key from a private key. This mirrors the functionality +* of `nacl.sign.keyPair.fromSeed()`, returning just the `publicKey` property. * -* @param {Uint8Array} seed - 32-byte private key +* @param {Uint8Array} privateKey - 32-byte private key * @returns {Uint8Array} 32-byte public key */ -export function derive (seed: Uint8Array): Uint8Array { - if (seed.length !== crypto_sign_SEEDBYTES) { - const err = `Invalid private key byte length to convert to public key, expected ${crypto_sign_SEEDBYTES}, actual ${seed.byteLength}` - trace(err, 1, seed.byteLength) +export function derive (k0: u64, k1: u64, k2: u64, k3: u64): Uint8Array { + const k = new Uint64Array(4); k.set([k0, k1, k2, k3]) + const privateKey = Uint8Array.wrap(k.buffer) + if (privateKey.byteLength !== PRIVATEKEY_BYTES) { + const err = `Invalid private key byte length to convert to public key, expected ${PRIVATEKEY_BYTES}, actual ${privateKey.byteLength}` + trace(err, 1, privateKey.byteLength) throw new Error(err) } - const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES) + const publicKey = new Uint8Array(PUBLICKEY_BYTES) const p: Int64Array[] = [new Int64Array(16), new Int64Array(16), new Int64Array(16), new Int64Array(16)] - const h: Uint8Array = new Blake2b(64).update(seed).digest() + const h: Uint8Array = new Blake2b(64).update(privateKey).digest() h[0] &= 248 h[31] &= 127 h[31] |= 64 scalarbase(p, h) - pack(pk, p) + pack(publicKey, p) - return pk + return publicKey } /** -* Signs the message using the secret key and returns a signature. +* Signs the message using the private key and returns a signature. * * @param {Uint8Array} message - Message to sign * @param {Uint8Array} privateKey - 32-byte key to use for signing @@ -658,15 +661,15 @@ export function sign (h0: u64, h1: u64, h2: u64, h3: u64, k0: u64, k1: u64, k2: const k = new Uint64Array(4); k.set([k0, k1, k2, k3]) const message = Uint8Array.wrap(h.buffer) const privateKey = Uint8Array.wrap(k.buffer) - if (privateKey.byteLength !== crypto_sign_PRIVATEKEYBYTES) { - const err = `Invalid key byte length to sign message, expected ${crypto_sign_PRIVATEKEYBYTES}, actual ${privateKey.byteLength}` + if (privateKey.byteLength !== PRIVATEKEY_BYTES) { + const err = `Invalid key byte length to sign message, expected ${PRIVATEKEY_BYTES}, actual ${privateKey.byteLength}` trace(err, 1, privateKey.byteLength) throw new Error(err) } - const signed = new Uint8Array(crypto_sign_BYTES + message.length) - const publicKey = derive(privateKey) + const signed = new Uint8Array(SIGNATURE_BYTES + message.length) + const publicKey = derive(k0, k1, k2, k3) crypto_sign(signed, message, message.length, privateKey, publicKey) - const sig = new Uint8Array(crypto_sign_BYTES) + const sig = new Uint8Array(SIGNATURE_BYTES) for (let i = 0; i < sig.length; i++) { sig[i] = signed[i] } @@ -674,27 +677,38 @@ export function sign (h0: u64, h1: u64, h2: u64, h3: u64, k0: u64, k1: u64, k2: } /** -* Verifies a detached signature for a message. +* Verifies a signature on a blockhash against a public key. * -* @param {Uint8Array} message - Signed message +* @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 `msg` and generate `sig`, else false +* @returns {boolean} - True if `publicKey` was used to sign `blockhash` and generate `signature`, else false */ -export function verify (message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean { - if (signature.byteLength !== crypto_sign_BYTES) { - const err = `Invalid signature size to verify signature, expected ${crypto_sign_BYTES}, actual ${signature.byteLength}` +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 { + 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]) + const blockhash = Uint8Array.wrap(h.buffer) + const signature = Uint8Array.wrap(s.buffer) + const publicKey = Uint8Array.wrap(k.buffer) + if (blockhash.byteLength !== BLOCKHASH_BYTES) { + const err = `Invalid blockhash size to verify signature, expected ${BLOCKHASH_BYTES}, actual ${blockhash.byteLength}` + trace(err, 1, blockhash.byteLength) + throw new Error(err) + } + if (signature.byteLength !== SIGNATURE_BYTES) { + const err = `Invalid signature size to verify signature, expected ${SIGNATURE_BYTES}, actual ${signature.byteLength}` trace(err, 1, signature.byteLength) throw new Error(err) } - if (publicKey.byteLength !== crypto_sign_PUBLICKEYBYTES) { - const err = `Invalid public key size to verify signature, expected ${crypto_sign_PUBLICKEYBYTES}, actual ${publicKey.byteLength}` + if (publicKey.byteLength !== PUBLICKEY_BYTES) { + const err = `Invalid public key size to verify signature, expected ${PUBLICKEY_BYTES}, actual ${publicKey.byteLength}` trace(err, 1, signature.byteLength) throw new Error(err) } - const sm = new Uint8Array(crypto_sign_BYTES + message.length) - const m = new Uint8Array(crypto_sign_BYTES + message.length) + const sm = new Uint8Array(SIGNATURE_BYTES + blockhash.length) + const m = new Uint8Array(SIGNATURE_BYTES + blockhash.length) sm.set(signature, 0) - sm.set(message, crypto_sign_BYTES) + sm.set(blockhash, SIGNATURE_BYTES) return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0) } -- 2.47.3