"package.json.license"
],
"main": "dist/main.js",
- "browser": "dist/main.min.js",
+ "browser": {
+ "dist/main.min.js": true,
+ "node:worker_threads": false
+ },
"repository": {
"type": "git",
"url": "git+https://zoso.dev/libnemo.git"
},
"scripts": {
- "build": "rm -rf dist && tsc && esbuild main.min=dist/main.js global.min=dist/global.js --outdir=dist --target=es2022 --format=esm --platform=browser --bundle --minify --sourcemap",
- "test": "npm run build && node --test --env-file .env",
+ "build": "rm -rf dist && tsc && esbuild main.min=dist/main.js global.min=dist/global.js --outdir=dist --target=es2022 --format=esm --bundle --minify --sourcemap",
+ "test": "npm run build -- --platform=node && node --test --env-file .env",
"test:coverage": "npm run test -- --experimental-test-coverage",
"test:coverage:report": "npm run test:coverage -- --test-reporter=lcov --test-reporter-destination=coverage.info && genhtml coverage.info --output-directory test/coverage && rm coverage.info && xdg-open test/coverage/index.html"
},
* calling function as an ArrayBuffer. This buffer can ultimately be processed
* using the `importKey()` method of the SubtleCrypto interface.
*/
-function passkey () {
+async function passkey () {
+ /**
+ * Polyfill for window methods which do not exist when executing Node.js tests.
+ */
+ if (globalThis.addEventListener == null || globalThis.postMessage == null) {
+ const { isMainThread, parentPort } = await import('node:worker_threads')
+ if (!isMainThread && parentPort) {
+ var addEventListener = Object.getPrototypeOf(parentPort).addListener.bind(parentPort)
+ var postMessage = Object.getPrototypeOf(parentPort).postMessage.bind(parentPort)
+ }
+ }
+
/**
* Message listener for this Web Worker thread.
*/
addEventListener('message', async (message: any) => {
- await polyfill()
const { password, iv } = message.data ?? message
const keyBuffer = await keygen(password, iv)
postMessage(keyBuffer, { transfer: [keyBuffer] })
)
return crypto.subtle.exportKey('raw', key)
}
-
- /**
- * Polyfill for window methods which do not exist when executing Node.js tests.
- */
- async function polyfill () {
- if (addEventListener == null || postMessage == null) {
- const { isMainThread, parentPort } = await import('node:worker_threads')
- if (!isMainThread && parentPort) {
- var addEventListener = Object.getPrototypeOf(parentPort).addListener.bind(parentPort)
- var postMessage = Object.getPrototypeOf(parentPort).postMessage.bind(parentPort)
- }
- }
- }
}
-const worker = new Blob(['(', passkey.toString(), ')()'], { type: 'application/javascript' })
-const workerUrl = URL.createObjectURL(worker)
+const workerUrl = `data:text/javascript,(${passkey.toString()})()`
export { workerUrl }
constructor () {
this.#storage = globalThis.sessionStorage
this.#thread = new Thread(workerUrl)
- URL.revokeObjectURL(workerUrl)
}
/**
const iv = new Entropy()
if (typeof passkey === 'string') {
try {
- // this.#thread.work({ password: passkey, iv: iv.bytes })
- passkey = await subtle.importKey('raw', utf8.toBytes(passkey), 'PBKDF2', false, ['deriveBits', 'deriveKey'])
- passkey = await subtle.deriveKey({ name: 'PBKDF2', hash: 'SHA-512', salt: iv.bytes, iterations: 210000 }, passkey, { name: 'AES-GCM', length: 256 }, false, ['encrypt'])
+ const keyBuffer = await this.#thread.work({ password: passkey, iv: iv.bytes })
+ passkey = await subtle.importKey('raw', keyBuffer, 'AES-GCM', false, ['encrypt'])
+ // passkey = await subtle.importKey('raw', utf8.toBytes(passkey), 'PBKDF2', false, ['deriveBits', 'deriveKey'])
+ // passkey = await subtle.deriveKey({ name: 'PBKDF2', hash: 'SHA-512', salt: iv.bytes, iterations: 210000 }, passkey, { name: 'AES-GCM', length: 256 }, false, ['encrypt'])
} catch (err) {
throw new Error(ERR_MSG)
}
constructor (url: string | URL) {
this.#worker = new Worker(new URL(url, import.meta.url), { type: 'module' })
- this.#worker.addEventListener('message', (event) => {
- const result = event.data ?? event
+ this.#worker.addEventListener('message', (message) => {
+ const result = message.data ?? message
if (this.#task == null) {
throw new ReferenceError(`Error resolving Worker result: ${result}`)
}
await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
\r
assert.ok('id' in wallet)\r
+ assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
assert.ok('mnemonic' in wallet)\r
+ assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
assert.ok('seed' in wallet)\r
+ assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
})\r
\r
it('BLAKE2b wallet with random entropy', async () => {\r
await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
\r
assert.ok('id' in wallet)\r
+ assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
assert.ok('mnemonic' in wallet)\r
+ assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
assert.ok('seed' in wallet)\r
+ assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
})\r
\r
it('BIP-44 replace invalid salt with empty string', async () => {\r
assert.ok(wallet)\r
})\r
})\r
+\r
+describe('wallet generation performance', { skip: true }, async () => {\r
+ it('performance test creating BIP-44 wallets', async () => {\r
+ const wallets = []\r
+ for (let i = 0x100; i > 0; i--) {\r
+ wallets.push(await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD))\r
+ }\r
+ assert.equal(wallets.length, 0x100)\r
+ })\r
+\r
+ it('performance test creating BLAKE2b wallets', async () => {\r
+ const wallets = []\r
+ for (let i = 0x100; i > 0; i--) {\r
+ wallets.push(await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD))\r
+ }\r
+ assert.equal(wallets.length, 0x100)\r
+ })\r
+})\r