From 07277eea2054ad298d58eff35e0c790b795ab221 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Sun, 24 Nov 2024 14:41:03 -0800 Subject: [PATCH] Restore changes to tweetnacl and prune extraneous functions created for testing and learning. --- src/lib/account.ts | 3 +- src/lib/workers/nano25519.ts | 162 +++++++++++++++++++---------------- 2 files changed, 88 insertions(+), 77 deletions(-) diff --git a/src/lib/account.ts b/src/lib/account.ts index b2b1910..e9fb73e 100644 --- a/src/lib/account.ts +++ b/src/lib/account.ts @@ -4,7 +4,7 @@ import blake2b from 'blake2b' import { ACCOUNT_KEY_LENGTH, ALPHABET, PREFIX, PREFIX_LEGACY } from './constants.js' import { base32, bytes, hex } from './convert.js' -import { getPublicKey, keyPair } from './workers/nano25519.js' +import { keyPair } from './workers/nano25519.js' import { Rpc } from './rpc.js' import { Safe } from './safe.js' @@ -87,7 +87,6 @@ export class Account { */ static async fromPrivateKey (key: string, index?: number): Promise { Account.#validateKey(key) - // const publicKey = getPublicKey(hex.toBytes(key)) const { publicKey } = keyPair.fromSeed(hex.toBytes(key)) const account = await Account.fromPublicKey(bytes.toHex(publicKey), index) account.#prv = key.toUpperCase() diff --git a/src/lib/workers/nano25519.ts b/src/lib/workers/nano25519.ts index f97313e..88b4246 100644 --- a/src/lib/workers/nano25519.ts +++ b/src/lib/workers/nano25519.ts @@ -17,29 +17,6 @@ import blake2b from 'blake2b' // 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 -/** -* Generate a public key from a private key using the Ed25519 algorithm. The key -* should be a cryptographically strong random value. -* -* @param {string} privateKey - 32-byte private key -* @returns {string} 32-byte public key -*/ -function getPublicKey (privateKey: Uint8Array): Uint8Array { - const h = blake2b(64).update(privateKey).digest().slice(0, 32) - return scalarMult.base(h) - // const pk = new Uint8Array(32) - // const p = [gf(),gf(),gf(),gf()] - // const h = blake2b(64).update(privateKey).digest().slice(0, 32) - - // h[0] &= 0xf8 - // h[31] &= 0x7f - // h[31] |= 0x40 - - // scalarbase(p, h) - // pack(pk, p) - - // return pk -} var gf = function(init?) { var i, r = new Float64Array(16); if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; @@ -47,7 +24,7 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { }; // Pluggable, initialized in high-level API below. - var randombytes = function(x, n) { throw new Error('no PRNG'); }; + var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; var _0 = new Uint8Array(16); var _9 = new Uint8Array(32); _9[0] = 9; @@ -2093,7 +2070,7 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { crypto_sign_SEEDBYTES = 32, crypto_hash_BYTES = 64; - export const lowlevel = { + nacl.lowlevel = { crypto_core_hsalsa20: crypto_core_hsalsa20, crypto_stream_xor: crypto_stream_xor, crypto_stream: crypto_stream, @@ -2164,9 +2141,9 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); } - function checkArrayTypes(...args) { - for (var i = 0; i < args.length; i++) { - if (!(args[i] instanceof Uint8Array)) + function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) throw new TypeError('unexpected type, use Uint8Array'); } } @@ -2175,13 +2152,38 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { for (var i = 0; i < arr.length; i++) arr[i] = 0; } - const randomBytes = function(n) { + nacl.randomBytes = function(n) { var b = new Uint8Array(n); randombytes(b, n); return b; }; - const scalarMult = function(n, p) { + nacl.secretbox = function(msg, nonce, key) { + checkArrayTypes(msg, nonce, key); + checkLengths(key, nonce); + var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); + var c = new Uint8Array(m.length); + for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i]; + crypto_secretbox(c, m, m.length, nonce, key); + return c.subarray(crypto_secretbox_BOXZEROBYTES); + }; + + nacl.secretbox.open = function(box, nonce, key) { + checkArrayTypes(box, nonce, key); + checkLengths(key, nonce); + var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length); + var m = new Uint8Array(c.length); + for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i]; + if (c.length < 32) return null; + if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return null; + return m.subarray(crypto_secretbox_ZEROBYTES); + }; + + nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES; + nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES; + nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES; + + nacl.scalarMult = function(n, p) { checkArrayTypes(n, p); if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); @@ -2190,7 +2192,7 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { return q; }; - scalarMult.base = function(n) { + nacl.scalarMult.base = function(n) { checkArrayTypes(n); if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); var q = new Uint8Array(crypto_scalarmult_BYTES); @@ -2198,50 +2200,63 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { return q; }; - scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES; - scalarMult.groupElementLength = crypto_scalarmult_BYTES; + nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES; + nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES; - const box = { - before: function(publicKey, secretKey) { + nacl.box = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox(msg, nonce, k); + }; + + nacl.box.before = function(publicKey, secretKey) { checkArrayTypes(publicKey, secretKey); checkBoxLengths(publicKey, secretKey); var k = new Uint8Array(crypto_box_BEFORENMBYTES); crypto_box_beforenm(k, publicKey, secretKey); return k; - }, - keyPair: { - create: () => { + }; + + nacl.box.after = nacl.secretbox; + + nacl.box.open = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox.open(msg, nonce, k); + }; + + nacl.box.open.after = nacl.secretbox.open; + + nacl.box.keyPair = function() { var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); crypto_box_keypair(pk, sk); return {publicKey: pk, secretKey: sk}; - }, - fromSecretKey: (secretKey) => { + }; + + nacl.box.keyPair.fromSecretKey = function(secretKey) { checkArrayTypes(secretKey); if (secretKey.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); crypto_scalarmult_base(pk, secretKey); return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; - } - }, - publicKeyLength: crypto_box_PUBLICKEYBYTES, - secretKeyLength: crypto_box_SECRETKEYBYTES, - sharedKeyLength: crypto_box_BEFORENMBYTES, - nonceLength: crypto_box_NONCEBYTES - } - - const message = { - sign: (msg, secretKey) => { + }; + + nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES; + nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES; + nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES; + nacl.box.nonceLength = crypto_box_NONCEBYTES; + nacl.box.overheadLength = nacl.secretbox.overheadLength; + + nacl.sign = function(msg, secretKey) { checkArrayTypes(msg, secretKey); if (secretKey.length !== crypto_sign_SECRETKEYBYTES) throw new Error('bad secret key size'); var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); crypto_sign(signedMsg, msg, msg.length, secretKey); return signedMsg; - }, + }; - open: (signedMsg, publicKey) => { + nacl.sign.open = function(signedMsg, publicKey) { checkArrayTypes(signedMsg, publicKey); if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) throw new Error('bad public key size'); @@ -2251,16 +2266,16 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { var m = new Uint8Array(mlen); for (var i = 0; i < m.length; i++) m[i] = tmp[i]; return m; - }, + }; - detach: (msg, secretKey) => { + nacl.sign.detached = function(msg, secretKey) { var signedMsg = nacl.sign(msg, secretKey); var sig = new Uint8Array(crypto_sign_BYTES); for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; return sig; - }, + }; - verify:(msg, sig, publicKey) => { + nacl.sign.detached.verify = function(msg, sig, publicKey) { checkArrayTypes(msg, sig, publicKey); if (sig.length !== crypto_sign_BYTES) throw new Error('bad signature size'); @@ -2272,27 +2287,25 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); - } - } + }; - const keyPair = { - create: () => { + nacl.sign.keyPair = function() { var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); crypto_sign_keypair(pk, sk); return {publicKey: pk, secretKey: sk}; - }, + }; - fromSecretKey: (secretKey) => { + nacl.sign.keyPair.fromSecretKey = function(secretKey) { checkArrayTypes(secretKey); if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error(`bad secret key size ${secretKey.length}`); + throw new Error('bad secret key size'); var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; - }, + }; - fromSeed: (seed) => { + nacl.sign.keyPair.fromSeed = function(seed) { checkArrayTypes(seed); if (seed.length !== crypto_sign_SEEDBYTES) throw new Error('bad seed size'); @@ -2301,24 +2314,23 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { for (var i = 0; i < 32; i++) sk[i] = seed[i]; crypto_sign_keypair(pk, sk, true); return {publicKey: pk, secretKey: sk}; - } - } + }; - export let publicKeyLength = crypto_sign_PUBLICKEYBYTES; - export let secretKeyLength = crypto_sign_SECRETKEYBYTES; - export let seedLength = crypto_sign_SEEDBYTES; - export let signatureLength = crypto_sign_BYTES; + nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES; + nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES; + nacl.sign.seedLength = crypto_sign_SEEDBYTES; + nacl.sign.signatureLength = crypto_sign_BYTES; - const hash = function(msg) { + nacl.hash = function(msg) { checkArrayTypes(msg); var h = new Uint8Array(crypto_hash_BYTES); crypto_hash(h, msg, msg.length); return h; }; - hash.hashLength = crypto_hash_BYTES; + nacl.hash.hashLength = crypto_hash_BYTES; - const verify = function(x, y) { + nacl.verify = function(x, y) { checkArrayTypes(x, y); // Zero length arguments are considered not equal. if (x.length === 0 || y.length === 0) return false; @@ -2326,7 +2338,7 @@ function getPublicKey (privateKey: Uint8Array): Uint8Array { return (vn(x, 0, y, 0, x.length) === 0) ? true : false; }; - const setPRNG = function(fn) { + nacl.setPRNG = function(fn) { randombytes = fn; }; -- 2.34.1