From 5fca820f9d9dce26bed97ca57fc20db3aff7e8f7 Mon Sep 17 00:00:00 2001 From: Pavel Prichodko <14926950+prichodko@users.noreply.github.com> Date: Fri, 8 Jul 2022 16:59:19 +0200 Subject: [PATCH 1/9] add pbkdf2 browser implementation --- .../status-js/src/crypto/pbkdf2.browser.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 packages/status-js/src/crypto/pbkdf2.browser.ts diff --git a/packages/status-js/src/crypto/pbkdf2.browser.ts b/packages/status-js/src/crypto/pbkdf2.browser.ts new file mode 100644 index 000000000..e248faea3 --- /dev/null +++ b/packages/status-js/src/crypto/pbkdf2.browser.ts @@ -0,0 +1,33 @@ +import type { pbkdf2 as pbkdf2Type } from 'ethereum-cryptography/pbkdf2' + +type PBKDF2 = typeof pbkdf2Type + +export const pbkdf2: PBKDF2 = async ( + password: Uint8Array, + salt: Uint8Array, + iterations: number, + keylen: number +): Promise => { + const cryptoKey = await window.crypto.subtle.importKey( + 'raw', + password, + { name: 'PBKDF2' }, + false, + ['deriveBits'] + ) + + const derivedKey = await window.crypto.subtle.deriveBits( + { + name: 'PBKDF2', + salt, + iterations, + hash: { + name: 'SHA-256', + }, + }, + cryptoKey, + keylen << 3 + ) + + return new Uint8Array(derivedKey) +} From e70ad9b4847bcc8201521b49c3e2e42651bd8d70 Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Mon, 18 Jul 2022 11:52:45 +0200 Subject: [PATCH 2/9] use webcrypto in pbkdf2 --- packages/status-js/package.json | 3 +++ .../status-js/src/crypto/pbkdf2.browser.ts | 21 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/status-js/package.json b/packages/status-js/package.json index 70534b9b6..ba3c7779a 100644 --- a/packages/status-js/package.json +++ b/packages/status-js/package.json @@ -50,5 +50,8 @@ ], "publishConfig": { "access": "public" + }, + "browser": { + "crypto": false } } diff --git a/packages/status-js/src/crypto/pbkdf2.browser.ts b/packages/status-js/src/crypto/pbkdf2.browser.ts index e248faea3..1af729835 100644 --- a/packages/status-js/src/crypto/pbkdf2.browser.ts +++ b/packages/status-js/src/crypto/pbkdf2.browser.ts @@ -1,14 +1,31 @@ +import _crypto from 'crypto' + import type { pbkdf2 as pbkdf2Type } from 'ethereum-cryptography/pbkdf2' type PBKDF2 = typeof pbkdf2Type +let crypto: Crypto + +if (globalThis.crypto) { + crypto = globalThis.crypto +} else if (_crypto.webcrypto) { + /** + * Note: allows debugging and testing with `vite-node` and `vitest` + * + * Note: `webcrypto` is experimental (@see https://nodejs.org/dist/latest-v16.x/docs/api/webcrypto.html#web-crypto-api) + */ + crypto = _crypto.webcrypto as unknown as Crypto +} else { + throw new Error('Crypto is not supported in this environment') +} + export const pbkdf2: PBKDF2 = async ( password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number ): Promise => { - const cryptoKey = await window.crypto.subtle.importKey( + const cryptoKey = await crypto.subtle.importKey( 'raw', password, { name: 'PBKDF2' }, @@ -16,7 +33,7 @@ export const pbkdf2: PBKDF2 = async ( ['deriveBits'] ) - const derivedKey = await window.crypto.subtle.deriveBits( + const derivedKey = await crypto.subtle.deriveBits( { name: 'PBKDF2', salt, From 4fdca3b607811fd3ee5fc9996d9e464dc2a89d65 Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Mon, 18 Jul 2022 12:05:49 +0200 Subject: [PATCH 3/9] rename pbkdf2 file --- packages/status-js/src/crypto/{pbkdf2.browser.ts => pbkdf2.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/status-js/src/crypto/{pbkdf2.browser.ts => pbkdf2.ts} (100%) diff --git a/packages/status-js/src/crypto/pbkdf2.browser.ts b/packages/status-js/src/crypto/pbkdf2.ts similarity index 100% rename from packages/status-js/src/crypto/pbkdf2.browser.ts rename to packages/status-js/src/crypto/pbkdf2.ts From 7d0865dd5291107a7812e26a7f589e1f4056199f Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Mon, 18 Jul 2022 12:07:46 +0200 Subject: [PATCH 4/9] use pbkdf2 --- packages/status-js/src/utils/generate-key-from-password.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/status-js/src/utils/generate-key-from-password.ts b/packages/status-js/src/utils/generate-key-from-password.ts index 5be4be648..8aae63ad5 100644 --- a/packages/status-js/src/utils/generate-key-from-password.ts +++ b/packages/status-js/src/utils/generate-key-from-password.ts @@ -1,6 +1,7 @@ -import { pbkdf2 } from 'ethereum-cryptography/pbkdf2' import { utf8ToBytes } from 'ethereum-cryptography/utils' +import { pbkdf2 } from '../crypto/pbkdf2' + const AES_KEY_LENGTH = 32 // bytes /** From 9a3b5d95950d6de820b22a391b9946a64157471f Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Mon, 18 Jul 2022 12:19:47 +0200 Subject: [PATCH 5/9] add changeset --- .changeset/itchy-apes-sin.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/itchy-apes-sin.md diff --git a/.changeset/itchy-apes-sin.md b/.changeset/itchy-apes-sin.md new file mode 100644 index 000000000..da4d052a7 --- /dev/null +++ b/.changeset/itchy-apes-sin.md @@ -0,0 +1,5 @@ +--- +'@status-im/js': patch +--- + +use built-in crypto for pbkdf2 From 2a97011b0ea9638fa50875a2a70a75b0d982027a Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Mon, 18 Jul 2022 16:30:43 +0200 Subject: [PATCH 6/9] revert rename --- .../status-js/src/crypto/pbkdf2.browser.ts | 33 ++++++++++++ packages/status-js/src/crypto/pbkdf2.ts | 50 ------------------- .../src/utils/generate-key-from-password.ts | 2 +- 3 files changed, 34 insertions(+), 51 deletions(-) create mode 100644 packages/status-js/src/crypto/pbkdf2.browser.ts delete mode 100644 packages/status-js/src/crypto/pbkdf2.ts diff --git a/packages/status-js/src/crypto/pbkdf2.browser.ts b/packages/status-js/src/crypto/pbkdf2.browser.ts new file mode 100644 index 000000000..e248faea3 --- /dev/null +++ b/packages/status-js/src/crypto/pbkdf2.browser.ts @@ -0,0 +1,33 @@ +import type { pbkdf2 as pbkdf2Type } from 'ethereum-cryptography/pbkdf2' + +type PBKDF2 = typeof pbkdf2Type + +export const pbkdf2: PBKDF2 = async ( + password: Uint8Array, + salt: Uint8Array, + iterations: number, + keylen: number +): Promise => { + const cryptoKey = await window.crypto.subtle.importKey( + 'raw', + password, + { name: 'PBKDF2' }, + false, + ['deriveBits'] + ) + + const derivedKey = await window.crypto.subtle.deriveBits( + { + name: 'PBKDF2', + salt, + iterations, + hash: { + name: 'SHA-256', + }, + }, + cryptoKey, + keylen << 3 + ) + + return new Uint8Array(derivedKey) +} diff --git a/packages/status-js/src/crypto/pbkdf2.ts b/packages/status-js/src/crypto/pbkdf2.ts deleted file mode 100644 index 1af729835..000000000 --- a/packages/status-js/src/crypto/pbkdf2.ts +++ /dev/null @@ -1,50 +0,0 @@ -import _crypto from 'crypto' - -import type { pbkdf2 as pbkdf2Type } from 'ethereum-cryptography/pbkdf2' - -type PBKDF2 = typeof pbkdf2Type - -let crypto: Crypto - -if (globalThis.crypto) { - crypto = globalThis.crypto -} else if (_crypto.webcrypto) { - /** - * Note: allows debugging and testing with `vite-node` and `vitest` - * - * Note: `webcrypto` is experimental (@see https://nodejs.org/dist/latest-v16.x/docs/api/webcrypto.html#web-crypto-api) - */ - crypto = _crypto.webcrypto as unknown as Crypto -} else { - throw new Error('Crypto is not supported in this environment') -} - -export const pbkdf2: PBKDF2 = async ( - password: Uint8Array, - salt: Uint8Array, - iterations: number, - keylen: number -): Promise => { - const cryptoKey = await crypto.subtle.importKey( - 'raw', - password, - { name: 'PBKDF2' }, - false, - ['deriveBits'] - ) - - const derivedKey = await crypto.subtle.deriveBits( - { - name: 'PBKDF2', - salt, - iterations, - hash: { - name: 'SHA-256', - }, - }, - cryptoKey, - keylen << 3 - ) - - return new Uint8Array(derivedKey) -} diff --git a/packages/status-js/src/utils/generate-key-from-password.ts b/packages/status-js/src/utils/generate-key-from-password.ts index 8aae63ad5..67d54d2ba 100644 --- a/packages/status-js/src/utils/generate-key-from-password.ts +++ b/packages/status-js/src/utils/generate-key-from-password.ts @@ -1,6 +1,6 @@ import { utf8ToBytes } from 'ethereum-cryptography/utils' -import { pbkdf2 } from '../crypto/pbkdf2' +import { pbkdf2 } from '../crypto/pbkdf2.browser' const AES_KEY_LENGTH = 32 // bytes From 9075907a4d2b8f0222783b3f21af03582c2380e3 Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Mon, 18 Jul 2022 16:31:11 +0200 Subject: [PATCH 7/9] remove browser field from package.json --- packages/status-js/package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/status-js/package.json b/packages/status-js/package.json index ba3c7779a..70534b9b6 100644 --- a/packages/status-js/package.json +++ b/packages/status-js/package.json @@ -50,8 +50,5 @@ ], "publishConfig": { "access": "public" - }, - "browser": { - "crypto": false } } From 50d934f78614348f0703ddb93b2426f2b2665fe8 Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Mon, 18 Jul 2022 16:32:09 +0200 Subject: [PATCH 8/9] use `resolve.alias` for pbkdf2 if test --- packages/status-js/vite.config.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/status-js/vite.config.ts b/packages/status-js/vite.config.ts index 96cb40f5b..f1e9a901f 100644 --- a/packages/status-js/vite.config.ts +++ b/packages/status-js/vite.config.ts @@ -4,12 +4,28 @@ import { defineConfig } from 'vite' import { dependencies } from './package.json' +import type { Alias } from 'vite' + +const isTest = process.env.NODE_ENV === 'test' + const external = [ ...Object.keys(dependencies || {}), // ...Object.keys(peerDependencies || {}), ].map(name => new RegExp(`^${name}(/.*)?`)) export default defineConfig(({ mode }) => { + const alias: Alias[] = [] + + if (isTest) { + alias.push({ + /** + * Note: `happy-dom` nor `jsdom` have Crypto implemented (@see https://github.com/jsdom/jsdom/issues/1612) + */ + find: /^.*\/crypto\/pbkdf2.browser$/, + replacement: 'ethereum-cryptography/pbkdf2', + }) + } + return { build: { target: 'es2020', @@ -24,9 +40,11 @@ export default defineConfig(({ mode }) => { external, }, }, - + resolve: { + alias, + }, test: { - // environment: 'happy-dom', + environment: 'happy-dom', }, } }) From eb9e865073dbe88cd5711facd14b2ed37251c66c Mon Sep 17 00:00:00 2001 From: Felicio Mununga Date: Tue, 19 Jul 2022 11:08:33 +0200 Subject: [PATCH 9/9] use `mode` in vite.config.ts --- packages/status-js/vite.config.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/status-js/vite.config.ts b/packages/status-js/vite.config.ts index f1e9a901f..01a77a866 100644 --- a/packages/status-js/vite.config.ts +++ b/packages/status-js/vite.config.ts @@ -6,8 +6,6 @@ import { dependencies } from './package.json' import type { Alias } from 'vite' -const isTest = process.env.NODE_ENV === 'test' - const external = [ ...Object.keys(dependencies || {}), // ...Object.keys(peerDependencies || {}), @@ -16,7 +14,7 @@ const external = [ export default defineConfig(({ mode }) => { const alias: Alias[] = [] - if (isTest) { + if (mode === 'test') { alias.push({ /** * Note: `happy-dom` nor `jsdom` have Crypto implemented (@see https://github.com/jsdom/jsdom/issues/1612)