From 183b4454c9a23e452ce2f2ef0599dd2b4fd41c42 Mon Sep 17 00:00:00 2001 From: Frederik Rothenberger Date: Tue, 19 Mar 2024 09:42:26 +0100 Subject: [PATCH 1/3] Upgrade agent-js This PR upgrades `agent-js` to the latest version to fix a bug related to WebAuthn registrations. Fixes #2235. --- demos/test-app/src/index.tsx | 10 +-- package-lock.json | 92 +++++++++++++++---------- package.json | 12 ++-- src/frontend/src/crypto/ed25519.test.ts | 8 +-- src/frontend/src/crypto/mnemonic.ts | 7 +- src/frontend/src/utils/iiConnection.ts | 3 +- src/vite-plugins/package.json | 2 +- 7 files changed, 74 insertions(+), 60 deletions(-) diff --git a/demos/test-app/src/index.tsx b/demos/test-app/src/index.tsx index cccf7880d4..b60dd77d76 100644 --- a/demos/test-app/src/index.tsx +++ b/demos/test-app/src/index.tsx @@ -347,11 +347,13 @@ init(); whoamiBtn.addEventListener("click", async () => { const canisterId = Principal.fromText(readCanisterId()); + let agent = new HttpAgent({ + host: hostUrlEl.value, + identity: delegationIdentity, + }); + await agent.fetchRootKey(); const actor = Actor.createActor(idlFactory, { - agent: new HttpAgent({ - host: hostUrlEl.value, - identity: delegationIdentity, - }), + agent, canisterId, }); diff --git a/package-lock.json b/package-lock.json index 7da2fe894b..c2e6fb1cf8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,13 +17,13 @@ "src/sig-verifier-js" ], "dependencies": { - "@dfinity/agent": "^0.19.2", - "@dfinity/auth-client": "^0.19.2", - "@dfinity/candid": "^0.19.2", - "@dfinity/identity": "^0.19.2", + "@dfinity/agent": "^1.1.1", + "@dfinity/auth-client": "^1.1.1", + "@dfinity/candid": "^1.1.1", + "@dfinity/identity": "^1.1.1", "@dfinity/internet-identity-vc-api": "*", - "@dfinity/principal": "^0.19.2", - "@dfinity/utils": "^0.0.20", + "@dfinity/principal": "^1.1.1", + "@dfinity/utils": "^2.1.2", "bip39": "^3.0.4", "buffer": "^6.0.3", "dompurify": "^3.0.6", @@ -844,49 +844,55 @@ } }, "node_modules/@dfinity/agent": { - "version": "0.19.3", - "license": "Apache-2.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-1.1.1.tgz", + "integrity": "sha512-FR7Vd+WMKetuwVhan5qevzk7QnsR44IfooaRjB/PohO+DztIg77uNsYKieloqeBqsqkxYkSJc8hYoAQm64YHNw==", "dependencies": { + "@noble/curves": "^1.2.0", "@noble/hashes": "^1.3.1", "base64-arraybuffer": "^0.2.0", "borc": "^2.1.1", + "buffer": "^6.0.3", "simple-cbor": "^0.4.1" }, "peerDependencies": { - "@dfinity/candid": "^0.19.3", - "@dfinity/principal": "^0.19.3" + "@dfinity/candid": "^1.1.1", + "@dfinity/principal": "^1.1.1" } }, "node_modules/@dfinity/auth-client": { - "version": "0.19.3", - "license": "Apache-2.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@dfinity/auth-client/-/auth-client-1.1.1.tgz", + "integrity": "sha512-LQT+HSrac+8bApxdtuYW1bjsy52dsushL/2ze3ca5CaQAW3LxmToe/8ePBwjamvDAvhZvmlODPpKvxmLFyP9iw==", "dependencies": { "idb": "^7.0.2" }, "peerDependencies": { - "@dfinity/agent": "^0.19.3", - "@dfinity/identity": "^0.19.3", - "@dfinity/principal": "^0.19.3" + "@dfinity/agent": "^1.1.1", + "@dfinity/identity": "^1.1.1", + "@dfinity/principal": "^1.1.1" } }, "node_modules/@dfinity/candid": { - "version": "0.19.3", - "license": "Apache-2.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-1.1.1.tgz", + "integrity": "sha512-CQlM5zWkzdlZ5tO4zQL6Ch0Wj9zROJpQ6Lcof8d3OE42FMIQwpLQeDKQ3i/CtxDuIHYia8dFI0rxM1E96WBpKQ==", "peerDependencies": { - "@dfinity/principal": "^0.19.3" + "@dfinity/principal": "^1.1.1" } }, "node_modules/@dfinity/identity": { - "version": "0.19.3", - "license": "Apache-2.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@dfinity/identity/-/identity-1.1.1.tgz", + "integrity": "sha512-GGMk9uYquyeZ4c1sPgsm+Iw3GVl0Qm6czVRTBaztZGk3Pmw8/+6byDSQiLqFApBwQCxit7uVozMR0fXC2IuENQ==", "dependencies": { + "@noble/curves": "^1.2.0", "@noble/hashes": "^1.3.1", - "borc": "^2.1.1", - "tweetnacl": "^1.0.1" + "borc": "^2.1.1" }, "peerDependencies": { - "@dfinity/agent": "^0.19.3", - "@dfinity/principal": "^0.19.3", + "@dfinity/agent": "^1.1.1", + "@dfinity/principal": "^1.1.1", "@peculiar/webcrypto": "^1.4.0" } }, @@ -903,8 +909,9 @@ "link": true }, "node_modules/@dfinity/principal": { - "version": "0.19.3", - "license": "Apache-2.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-1.1.1.tgz", + "integrity": "sha512-nXk8Cx01Y76/FAjYlMQHUpiI4cJkafAksgvnWFljIFWQMvOzjo2YCUIcZ3H+aVtEXJpXy61a6aseSSUQuaxlVw==", "dependencies": { "@noble/hashes": "^1.3.1" } @@ -914,12 +921,13 @@ "link": true }, "node_modules/@dfinity/utils": { - "version": "0.0.20", - "license": "Apache-2.0", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@dfinity/utils/-/utils-2.1.2.tgz", + "integrity": "sha512-iMbprcyLOQFhrvvb5b51acDvSsnXmMEpGBC/dwFNEDQBMPeX/rB3lm9HUOQf3ga1wOs20pYi4Rh42xVXhvmHdg==", "peerDependencies": { - "@dfinity/agent": "^0.19.1", - "@dfinity/candid": "^0.19.1", - "@dfinity/principal": "^0.19.1" + "@dfinity/agent": "^1.0.1", + "@dfinity/candid": "^1.0.1", + "@dfinity/principal": "^1.0.1" } }, "node_modules/@dfinity/vc_util_js": { @@ -1568,9 +1576,21 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@noble/curves": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", + "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@noble/hashes": { - "version": "1.3.2", - "license": "MIT", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "engines": { "node": ">= 16" }, @@ -12359,10 +12379,6 @@ "node": "*" } }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "license": "Unlicense" - }, "node_modules/type-detect": { "version": "4.0.8", "dev": true, @@ -14681,7 +14697,7 @@ "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE.md", "devDependencies": { - "@dfinity/utils": "^0.0.20", + "@dfinity/utils": "^2.1.2", "@types/html-minifier-terser": "^7.0.0", "html-minifier-terser": "^7.2.0", "typescript": "*", diff --git a/package.json b/package.json index e670d11be3..3203c2b14d 100644 --- a/package.json +++ b/package.json @@ -57,13 +57,13 @@ "webdriverio": "8.32.3" }, "dependencies": { - "@dfinity/agent": "^0.19.2", - "@dfinity/auth-client": "^0.19.2", - "@dfinity/candid": "^0.19.2", - "@dfinity/identity": "^0.19.2", + "@dfinity/agent": "^1.1.1", + "@dfinity/auth-client": "^1.1.1", + "@dfinity/candid": "^1.1.1", + "@dfinity/identity": "^1.1.1", "@dfinity/internet-identity-vc-api": "*", - "@dfinity/principal": "^0.19.2", - "@dfinity/utils": "^0.0.20", + "@dfinity/principal": "^1.1.1", + "@dfinity/utils": "^2.1.2", "bip39": "^3.0.4", "buffer": "^6.0.3", "dompurify": "^3.0.6", diff --git a/src/frontend/src/crypto/ed25519.test.ts b/src/frontend/src/crypto/ed25519.test.ts index 1999de5271..810978623e 100644 --- a/src/frontend/src/crypto/ed25519.test.ts +++ b/src/frontend/src/crypto/ed25519.test.ts @@ -1,5 +1,5 @@ +import { fromHex } from "@dfinity/agent"; import { Ed25519PublicKey } from "@dfinity/identity"; -import { fromHexString } from "@dfinity/identity/lib/cjs/buffer"; import * as ed25519 from "./ed25519"; type TestVector = { @@ -66,9 +66,9 @@ const testVectorsSLIP10 = [ test("derive Ed25519 via SLIP 0010", async () => { await Promise.all( testVectorsSLIP10.map(async (testVector: TestVector) => { - const seedBlob = fromHexString(testVector.seed); - const expectedPrivateKey = fromHexString(testVector.privateKey); - const expectedPublicKey = fromHexString(testVector.publicKey); + const seedBlob = fromHex(testVector.seed); + const expectedPrivateKey = fromHex(testVector.privateKey); + const expectedPublicKey = fromHex(testVector.publicKey); const identity = await ed25519.fromSeedWithSlip0010( new Uint8Array(seedBlob), diff --git a/src/frontend/src/crypto/mnemonic.ts b/src/frontend/src/crypto/mnemonic.ts index 75ea8fa988..26dbfad151 100644 --- a/src/frontend/src/crypto/mnemonic.ts +++ b/src/frontend/src/crypto/mnemonic.ts @@ -1,5 +1,5 @@ import { isUserNumber } from "$src/utils/userNumber"; -import { toHexString } from "@dfinity/identity/lib/cjs/buffer"; +import { toHex } from "@dfinity/agent"; import { entropyToMnemonic, validateMnemonic, wordlists } from "bip39"; /** @@ -8,10 +8,7 @@ import { entropyToMnemonic, validateMnemonic, wordlists } from "bip39"; export function generate(): string { const entropy = new Uint32Array(8); // NOTE: please change RECOVERYPHRASE_WORDCOUNT if this changes crypto.getRandomValues(entropy); - return entropyToMnemonic( - toHexString(entropy.buffer), - RECOVERYPHRASE_WORDLIST - ); + return entropyToMnemonic(toHex(entropy.buffer), RECOVERYPHRASE_WORDLIST); } /** How many words are expected in the recovery phrase */ diff --git a/src/frontend/src/utils/iiConnection.ts b/src/frontend/src/utils/iiConnection.ts index 147852f0f9..9fc3d9999a 100644 --- a/src/frontend/src/utils/iiConnection.ts +++ b/src/frontend/src/utils/iiConnection.ts @@ -43,7 +43,6 @@ import { } from "@dfinity/identity"; import { Principal } from "@dfinity/principal"; import { isNullish, nonNullish } from "@dfinity/utils"; -import * as tweetnacl from "tweetnacl"; import { MultiWebAuthnIdentity } from "./multiWebAuthnIdentity"; import { RecoveryDevice, isRecoveryDevice } from "./recoveryDevice"; import { isWebAuthnCancel } from "./webAuthnErrorUtils"; @@ -719,7 +718,7 @@ export const creationOptions = ( name: "Internet Identity Service", }, user: { - id: tweetnacl.randomBytes(16), + id: window.crypto.getRandomValues(new Uint8Array(16)), name: "Internet Identity", displayName: "Internet Identity", }, diff --git a/src/vite-plugins/package.json b/src/vite-plugins/package.json index 4af4bf4fe2..93de60003d 100644 --- a/src/vite-plugins/package.json +++ b/src/vite-plugins/package.json @@ -25,7 +25,7 @@ "vite": "^4.5.2", "undici": "*", "vite-plugin-compression": "^0.5.1", - "@dfinity/utils": "^0.0.20", + "@dfinity/utils": "^2.1.2", "@types/html-minifier-terser": "^7.0.0", "html-minifier-terser": "^7.2.0" } From d4ef2b9bbe5505bc642192a0c824a1c3fe0148d3 Mon Sep 17 00:00:00 2001 From: Frederik Rothenberger Date: Wed, 20 Mar 2024 15:00:50 +0100 Subject: [PATCH 2/3] Switch let to const --- demos/test-app/src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/test-app/src/index.tsx b/demos/test-app/src/index.tsx index b60dd77d76..e896c3d810 100644 --- a/demos/test-app/src/index.tsx +++ b/demos/test-app/src/index.tsx @@ -347,7 +347,7 @@ init(); whoamiBtn.addEventListener("click", async () => { const canisterId = Principal.fromText(readCanisterId()); - let agent = new HttpAgent({ + const agent = new HttpAgent({ host: hostUrlEl.value, identity: delegationIdentity, }); From ab18d362254535aff072809fbab1f0c26c55bedb Mon Sep 17 00:00:00 2001 From: Frederik Rothenberger Date: Wed, 20 Mar 2024 15:12:26 +0100 Subject: [PATCH 3/3] Switch to/fromHex to to/fromHexString --- src/frontend/src/crypto/ed25519.test.ts | 8 ++++---- src/frontend/src/crypto/mnemonic.ts | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/crypto/ed25519.test.ts b/src/frontend/src/crypto/ed25519.test.ts index 810978623e..9af23de542 100644 --- a/src/frontend/src/crypto/ed25519.test.ts +++ b/src/frontend/src/crypto/ed25519.test.ts @@ -1,4 +1,4 @@ -import { fromHex } from "@dfinity/agent"; +import { fromHexString } from "@dfinity/candid"; import { Ed25519PublicKey } from "@dfinity/identity"; import * as ed25519 from "./ed25519"; @@ -66,9 +66,9 @@ const testVectorsSLIP10 = [ test("derive Ed25519 via SLIP 0010", async () => { await Promise.all( testVectorsSLIP10.map(async (testVector: TestVector) => { - const seedBlob = fromHex(testVector.seed); - const expectedPrivateKey = fromHex(testVector.privateKey); - const expectedPublicKey = fromHex(testVector.publicKey); + const seedBlob = fromHexString(testVector.seed); + const expectedPrivateKey = fromHexString(testVector.privateKey); + const expectedPublicKey = fromHexString(testVector.publicKey); const identity = await ed25519.fromSeedWithSlip0010( new Uint8Array(seedBlob), diff --git a/src/frontend/src/crypto/mnemonic.ts b/src/frontend/src/crypto/mnemonic.ts index 26dbfad151..9e539ef6c9 100644 --- a/src/frontend/src/crypto/mnemonic.ts +++ b/src/frontend/src/crypto/mnemonic.ts @@ -1,5 +1,5 @@ import { isUserNumber } from "$src/utils/userNumber"; -import { toHex } from "@dfinity/agent"; +import { toHexString } from "@dfinity/candid"; import { entropyToMnemonic, validateMnemonic, wordlists } from "bip39"; /** @@ -8,7 +8,10 @@ import { entropyToMnemonic, validateMnemonic, wordlists } from "bip39"; export function generate(): string { const entropy = new Uint32Array(8); // NOTE: please change RECOVERYPHRASE_WORDCOUNT if this changes crypto.getRandomValues(entropy); - return entropyToMnemonic(toHex(entropy.buffer), RECOVERYPHRASE_WORDLIST); + return entropyToMnemonic( + toHexString(entropy.buffer), + RECOVERYPHRASE_WORDLIST + ); } /** How many words are expected in the recovery phrase */