From 94a0be64a4a7612b211c201db1c53d29e0370be9 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Sun, 1 Dec 2024 12:45:39 -0800 Subject: [PATCH] Reorganize NanoNaCl exports and imports. Remove some logging from test attempts and start converting vars to lets and consts as appropriate. --- src/lib/account.ts | 4 +- src/lib/block.ts | 6 +- src/lib/{workers => }/nano-nacl.ts | 126 ++++++++++++++--------------- src/lib/tools.ts | 6 +- src/lib/workers.ts | 5 +- 5 files changed, 71 insertions(+), 76 deletions(-) rename src/lib/{workers => }/nano-nacl.ts (84%) diff --git a/src/lib/account.ts b/src/lib/account.ts index 8d12132..9933282 100644 --- a/src/lib/account.ts +++ b/src/lib/account.ts @@ -6,7 +6,7 @@ import { ACCOUNT_KEY_LENGTH, ALPHABET, PREFIX, PREFIX_LEGACY } from './constants import { base32, bytes, hex } from './convert.js' import { Rpc } from './rpc.js' import { Safe } from './safe.js' -import { nacl } from './workers/nano-nacl.js' +import { NanoNaCl } from './nano-nacl.js' /** * Represents a single Nano address and the associated public key. To include the @@ -109,7 +109,7 @@ export class Account { static fromPrivateKey (privateKey: string, index?: number): Account { Account.#isInternal = true Account.#validateKey(privateKey) - const { publicKey } = nacl.keyPair(hex.toBytes(privateKey)) + const { publicKey } = NanoNaCl.keyPair(hex.toBytes(privateKey)) const account = Account.fromPublicKey(bytes.toHex(publicKey), index) account.#prv = privateKey.toUpperCase() return account diff --git a/src/lib/block.ts b/src/lib/block.ts index 14a244f..bc50ad3 100644 --- a/src/lib/block.ts +++ b/src/lib/block.ts @@ -6,7 +6,7 @@ import { Account } from './account.js' import { bytes, dec, hex } from './convert.js' import { Rpc } from './rpc.js' import Tools from './tools.js' -import { nacl } from './workers/nano-nacl.js' +import { NanoNaCl } from './nano-nacl.js' /** * Represents a block as defined by the Nano cryptocurrency protocol. The Block @@ -141,7 +141,7 @@ abstract class Block { } const account = await Account.fromPrivateKey(key) try { - const signature = nacl.sign( + const signature = NanoNaCl.sign( hex.toBytes(await this.hash()), hex.toBytes(`${account.privateKey}${account.publicKey}`) ) @@ -201,7 +201,7 @@ abstract class Block { this.link ] const hash = await Tools.hash(data, 'hex') - return nacl.verify( + return NanoNaCl.verify( hex.toBytes(hash), hex.toBytes(this.signature ?? ''), hex.toBytes(key) diff --git a/src/lib/workers/nano-nacl.ts b/src/lib/nano-nacl.ts similarity index 84% rename from src/lib/workers/nano-nacl.ts rename to src/lib/nano-nacl.ts index ec61da8..e288e4e 100644 --- a/src/lib/workers/nano-nacl.ts +++ b/src/lib/nano-nacl.ts @@ -3,6 +3,8 @@ //@ts-nocheck 'use strict' +import { Blake2b } from './blake2b.js' + // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. // Public domain. // @@ -15,24 +17,22 @@ // See for details: https://docs.nano.org/integration-guides/the-basics/ // Original source commit: https://github.com/dchest/tweetnacl-js/blob/71df1d6a1d78236ca3e9f6c788786e21f5a651a6/nacl-fast.js -const NanoNaCl = () => { +const n = () => { /** * Listens for messages from a calling function. */ addEventListener('message', (message) => { const data = JSON.parse(new TextDecoder().decode(message.data ?? message)) - // for (const d of data) { - for (let i = 0; i < data.length; i++) { - if (i % 100 === 0) console.log(`${i} keys`) - data[i].publicKey = hexify(keyPair(data[i].privateKey).publicKey) + for (const d of data) { + d.publicKey = hexify(keyPair(d.privateKey).publicKey) } const buf = new TextEncoder().encode(JSON.stringify(data)).buffer postMessage(buf, [buf]) }) var gf = function (init?: number[]) { - var i, r = new Float64Array(16) - if (init) for (i = 0; i < init.length; i++) r[i] = init[i] + const r = new Float64Array(16) + if (init) for (let i = 0; i < init.length; i++) r[i] = init[i] return r } @@ -122,15 +122,15 @@ const NanoNaCl = () => { } function A (o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] + b[i] + for (let i = 0; i < 16; i++) o[i] = a[i] + b[i] } function Z (o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] - b[i] + for (let i = 0; i < 16; i++) o[i] = a[i] - b[i] } function M (o, a, b) { - var v, c, + let v, c, t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, @@ -528,15 +528,15 @@ const NanoNaCl = () => { // Note: difference from TweetNaCl - BLAKE2b used to hash instead of SHA-512. function crypto_hash (out: Uint8Array, m: Uint8Array, n: number) { + const input = new Uint8Array(n) + for (let i = 0; i < n; ++i) input[i] = m[i] const hash = new Blake2b(64).update(m).digest() - for (let i = 0; i < 64; ++i) { - out[i] = hash[i] - } + for (let i = 0; i < 64; ++i) out[i] = hash[i] return 0 } function add (p, q) { - var a = gf(), b = gf(), c = gf(), + const a = gf(), b = gf(), c = gf(), d = gf(), e = gf(), f = gf(), g = gf(), h = gf(), t = gf() @@ -562,14 +562,13 @@ const NanoNaCl = () => { } function cswap (p, q, b) { - var i - for (i = 0; i < 4; i++) { + for (let i = 0; i < 4; i++) { sel25519(p[i], q[i], b) } } function pack (r, p) { - var tx = gf(), ty = gf(), zi = gf() + const tx = gf(), ty = gf(), zi = gf() inv25519(zi, p[2]) M(tx, p[0], zi) M(ty, p[1], zi) @@ -578,13 +577,12 @@ const NanoNaCl = () => { } function scalarmult (p, q, s) { - var b, i set25519(p[0], gf0) set25519(p[1], gf1) set25519(p[2], gf1) set25519(p[3], gf0) - for (i = 255; i >= 0; --i) { - b = (s[(i / 8) | 0] >> (i & 7)) & 1 + for (let i = 255; i >= 0; --i) { + const b = (s[(i / 8) | 0] >> (i & 7)) & 1 cswap(p, q, b) add(q, p) add(p, p) @@ -593,7 +591,7 @@ const NanoNaCl = () => { } function scalarbase (p, s) { - var q = [gf(), gf(), gf(), gf()] + const q = [gf(), gf(), gf(), gf()] set25519(q[0], X) set25519(q[1], Y) set25519(q[2], gf1) @@ -601,27 +599,10 @@ const NanoNaCl = () => { scalarmult(p, q, s) } - function crypto_sign_keypair (pk: Uint8Array, sk: Uint8Array) { - var d = new Uint8Array(64) - var p = [gf(), gf(), gf(), gf()] - var i - - crypto_hash(d, sk, 32) - d[0] &= 248 - d[31] &= 127 - d[31] |= 64 - - scalarbase(p, d) - pack(pk, p) - - for (i = 0; i < 32; i++) sk[i + 32] = pk[i] - return 0 - } - - var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]) + const L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]) function modL (r, x) { - var carry, i, j, k + let carry, i, j, k for (i = 63; i >= 32; --i) { carry = 0 for (j = i - 32, k = i - 12; j < k; ++j) { @@ -646,7 +627,7 @@ const NanoNaCl = () => { } function reduce (r) { - var x = new Float64Array(64), i + let x = new Float64Array(64), i for (i = 0; i < 64; i++) x[i] = r[i] for (i = 0; i < 64; i++) r[i] = 0 modL(r, x) @@ -654,32 +635,32 @@ const NanoNaCl = () => { // Note: difference from C - smlen returned, not passed as argument. function crypto_sign (sm: Uint8Array, m: Uint8Array, n: number, sk: Uint8Array) { - var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64) - var i, j, x = new Float64Array(64) - var p = [gf(), gf(), gf(), gf()] + const d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64) + const x = new Float64Array(64) + const p = [gf(), gf(), gf(), gf()] crypto_hash(d, sk, 32) d[0] &= 248 d[31] &= 127 d[31] |= 64 - var smlen = n + 64 - for (i = 0; i < n; i++) sm[64 + i] = m[i] - for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i] + const smlen = n + 64 + for (let i = 0; i < n; i++) sm[64 + i] = m[i] + for (let i = 0; i < 32; i++) sm[32 + i] = d[32 + i] crypto_hash(r, sm.subarray(32), n + 32) reduce(r) scalarbase(p, r) pack(sm, p) - for (i = 32; i < 64; i++) sm[i] = sk[i] + for (let i = 32; i < 64; i++) sm[i] = sk[i] crypto_hash(h, sm, n + 64) reduce(h) - for (i = 0; i < 64; i++) x[i] = 0 - for (i = 0; i < 32; i++) x[i] = r[i] - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { + for (let i = 0; i < 64; i++) x[i] = 0 + for (let i = 0; i < 32; i++) x[i] = r[i] + for (let i = 0; i < 32; i++) { + for (let j = 0; j < 32; j++) { x[i + j] += h[i] * d[j] } } @@ -689,7 +670,7 @@ const NanoNaCl = () => { } function unpackneg (r, p) { - var t = gf(), chk = gf(), num = gf(), + const t = gf(), chk = gf(), num = gf(), den = gf(), den2 = gf(), den4 = gf(), den6 = gf() @@ -727,7 +708,6 @@ const NanoNaCl = () => { } function crypto_sign_open (m: Uint8Array, sm: Uint8Array, n: number, pk: Uint8Array) { - var i var t = new Uint8Array(32), h = new Uint8Array(64) var p = [gf(), gf(), gf(), gf()], q = [gf(), gf(), gf(), gf()] @@ -736,8 +716,8 @@ const NanoNaCl = () => { if (unpackneg(q, pk)) return -1 - for (i = 0; i < n; i++) m[i] = sm[i] - for (i = 0; i < 32; i++) m[i + 32] = pk[i] + for (let i = 0; i < n; i++) m[i] = sm[i] + for (let i = 0; i < 32; i++) m[i + 32] = pk[i] crypto_hash(h, m, n) reduce(h) scalarmult(p, q, h) @@ -748,11 +728,11 @@ const NanoNaCl = () => { n -= 64 if (crypto_verify_32(sm, 0, t, 0)) { - for (i = 0; i < n; i++) m[i] = 0 + for (let i = 0; i < n; i++) m[i] = 0 return -1 } - for (i = 0; i < n; i++) m[i] = sm[i + 64] + for (let i = 0; i < n; i++) m[i] = sm[i + 64] return n } @@ -765,10 +745,8 @@ const NanoNaCl = () => { function checkArrayTypes (...args: Uint8Array[]) { for (var i = 0; i < args.length; i++) { - if (!(args[i] instanceof Uint8Array)) { - console.log(args[i]) + if (!(args[i] instanceof Uint8Array)) throw new TypeError(`expected Uint8Array; received ${args[i].constructor?.name ?? typeof args[i]}`) - } } } @@ -835,16 +813,30 @@ const NanoNaCl = () => { checkArrayTypes(seed) if (seed.length !== crypto_sign_SEEDBYTES) throw new Error('bad seed size') - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES) - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES) - for (var i = 0; i < 32; i++) sk[i] = seed[i] - crypto_sign_keypair(pk, sk) + const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES) + const sk = new Uint8Array(crypto_sign_SECRETKEYBYTES) + for (let i = 0; i < 32; i++) sk[i] = seed[i] + + const p = [gf(), gf(), gf(), gf()] + + const hash = new Blake2b(64).update(sk).digest() + hash[0] &= 248 + hash[31] &= 127 + hash[31] |= 64 + + scalarbase(p, hash) + pack(pk, p) + + for (let i = 0; i < 32; i++) sk[i + 32] = pk[i] + return { publicKey: pk, secretKey: sk } } return { sign, open, detached, verify, keyPair } } -export const nacl = NanoNaCl() +export const NanoNaCl = n() -export default NanoNaCl.toString().substring(NanoNaCl.toString().indexOf('{') + 1, NanoNaCl.toString().lastIndexOf('return')) +const start = n.toString().indexOf('{') + 1 +const end = n.toString().lastIndexOf('return') +export const worker = n.toString().substring(start, end) diff --git a/src/lib/tools.ts b/src/lib/tools.ts index c4d5166..9c168ec 100644 --- a/src/lib/tools.ts +++ b/src/lib/tools.ts @@ -8,7 +8,7 @@ import { bytes, hex } from './convert.js' import { Rpc } from './rpc.js' import { Bip44Wallet, Blake2bWallet, LedgerWallet } from './wallet.js' import { SendBlock } from './block.js' -import { nacl } from './workers/nano-nacl.js' +import { NanoNaCl } from './nano-nacl.js' /** * Converts a decimal amount of nano from one unit divider to another. @@ -89,7 +89,7 @@ export async function hash (data: string | string[], encoding?: 'hex'): Promise< export async function sign (key: string, ...input: string[]): Promise { const account = await Account.fromPrivateKey(key) const data = await hash(input) - const signature = nacl.sign( + const signature = NanoNaCl.sign( hex.toBytes(data), hex.toBytes(`${account.privateKey}${account.publicKey}`)) return bytes.toHex(signature.subarray(0, 64)) @@ -160,7 +160,7 @@ export async function sweep (rpc: Rpc | string | URL, wallet: Blake2bWallet | Bi */ export async function verify (key: string, signature: string, ...input: string[]): Promise { const data = await hash(input) - return nacl.verify( + return NanoNaCl.verify( hex.toBytes(data), hex.toBytes(signature), hex.toBytes(key)) diff --git a/src/lib/workers.ts b/src/lib/workers.ts index d3c9e76..4367980 100644 --- a/src/lib/workers.ts +++ b/src/lib/workers.ts @@ -1,5 +1,8 @@ import ckdBip44 from './workers/ckdBip44.js' -import NanoNaCl from './workers/nano-nacl.js' +import { worker as NanoNaCl } from './nano-nacl.js' // import './workers/passkey.js' import pow from './workers/pow.js' + + + export { ckdBip44, NanoNaCl } -- 2.34.1