From 9535a76feb254799fc644301df0f05dffdf4d485 Mon Sep 17 00:00:00 2001 From: David McFadzean Date: Sun, 22 Feb 2026 18:06:34 -0500 Subject: [PATCH 1/2] feat: Add change passphrase to web clients (#114) Co-Authored-By: Claude Opus 4.6 --- .../src/components/WalletTab.tsx | 36 +++++++++++++++++ .../react-wallet/src/components/WalletTab.tsx | 40 ++++++++++++++++++- services/gatekeeper/client/src/KeymasterUI.js | 23 +++++++++++ services/keymaster/client/src/KeymasterUI.js | 23 +++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) diff --git a/apps/chrome-extension/src/components/WalletTab.tsx b/apps/chrome-extension/src/components/WalletTab.tsx index 36f66736..c1b882ad 100644 --- a/apps/chrome-extension/src/components/WalletTab.tsx +++ b/apps/chrome-extension/src/components/WalletTab.tsx @@ -7,6 +7,7 @@ import { useWalletContext } from "../contexts/WalletProvider"; import { useSnackbar } from "../contexts/SnackbarProvider"; import WarningModal from "../modals/WarningModal"; import MnemonicModal from "../modals/MnemonicModal"; +import PassphraseModal from "../modals/PassphraseModal"; import WalletChrome from "@didcid/keymaster/wallet/chrome"; const WalletTab = () => { @@ -17,6 +18,8 @@ const WalletTab = () => { const [checkingWallet, setCheckingWallet] = useState(false); const [showFixModal, setShowFixModal] = useState(false); const [checkResultMessage, setCheckResultMessage] = useState(""); + const [showChangePassphrase, setShowChangePassphrase] = useState(false); + const [changePassError, setChangePassError] = useState(""); const { keymaster, initialiseWallet, @@ -215,6 +218,21 @@ const WalletTab = () => { } } + async function handleChangePassphrase(newPassphrase: string) { + if (!keymaster) { + return; + } + try { + await keymaster.changePassphrase(newPassphrase); + await chrome.runtime.sendMessage({ action: "STORE_PASSPHRASE", passphrase: newPassphrase }); + setShowChangePassphrase(false); + setChangePassError(""); + setSuccess("Passphrase changed"); + } catch (error: any) { + setChangePassError(error?.message || "Failed to change passphrase"); + } + } + return ( { onClose={handleMnemonicModalClose} /> + { setShowChangePassphrase(false); setChangePassError(""); }} + encrypt={true} + showCancel={true} + /> )} + + )} + + +

diff --git a/services/keymaster/client/src/KeymasterUI.js b/services/keymaster/client/src/KeymasterUI.js index 497ea2fc..5dac3bf0 100644 --- a/services/keymaster/client/src/KeymasterUI.js +++ b/services/keymaster/client/src/KeymasterUI.js @@ -1885,6 +1885,24 @@ function KeymasterUI({ keymaster, title, challengeDID, onWalletUpload }) { } } + async function changePassphrase() { + try { + const newPass = window.prompt("Enter new passphrase:"); + if (!newPass) { + return; + } + const confirm = window.prompt("Confirm new passphrase:"); + if (newPass !== confirm) { + window.alert("Passphrases do not match"); + return; + } + await keymaster.changePassphrase(newPass); + showSuccess('Passphrase changed'); + } catch (error) { + showError(error); + } + } + async function uploadImage(event) { try { const fileInput = event.target; // Reference to the input element @@ -5361,6 +5379,11 @@ function KeymasterUI({ keymaster, title, challengeDID, onWalletUpload }) { Upload... + + +

From 3d80a2a315777c8633947bac71520d2160bcb32f Mon Sep 17 00:00:00 2001 From: David McFadzean Date: Sun, 22 Feb 2026 18:15:28 -0500 Subject: [PATCH 2/2] fix: Address PR review feedback for change passphrase - Fix import formatting (spaces inside braces) - Rename confirm to confirmPassphrase to avoid shadowing window.confirm - Use showError instead of window.alert for consistency with snackbar UX Co-Authored-By: Claude Opus 4.6 --- apps/react-wallet/src/components/WalletTab.tsx | 2 +- services/gatekeeper/client/src/KeymasterUI.js | 6 +++--- services/keymaster/client/src/KeymasterUI.js | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/react-wallet/src/components/WalletTab.tsx b/apps/react-wallet/src/components/WalletTab.tsx index 538bdc9a..26f3171b 100644 --- a/apps/react-wallet/src/components/WalletTab.tsx +++ b/apps/react-wallet/src/components/WalletTab.tsx @@ -9,7 +9,7 @@ import WarningModal from "../modals/WarningModal"; import MnemonicModal from "../modals/MnemonicModal"; import PassphraseModal from "../modals/PassphraseModal"; import WalletWeb from "@didcid/keymaster/wallet/web"; -import {clearSessionPassphrase, setSessionPassphrase} from "../utils/sessionPassphrase"; +import { clearSessionPassphrase, setSessionPassphrase } from "../utils/sessionPassphrase"; const WalletTab = () => { const [open, setOpen] = useState(false); diff --git a/services/gatekeeper/client/src/KeymasterUI.js b/services/gatekeeper/client/src/KeymasterUI.js index 5dac3bf0..3f2c336a 100644 --- a/services/gatekeeper/client/src/KeymasterUI.js +++ b/services/gatekeeper/client/src/KeymasterUI.js @@ -1891,9 +1891,9 @@ function KeymasterUI({ keymaster, title, challengeDID, onWalletUpload }) { if (!newPass) { return; } - const confirm = window.prompt("Confirm new passphrase:"); - if (newPass !== confirm) { - window.alert("Passphrases do not match"); + const confirmPassphrase = window.prompt("Confirm new passphrase:"); + if (newPass !== confirmPassphrase) { + showError("Passphrases do not match"); return; } await keymaster.changePassphrase(newPass); diff --git a/services/keymaster/client/src/KeymasterUI.js b/services/keymaster/client/src/KeymasterUI.js index 5dac3bf0..3f2c336a 100644 --- a/services/keymaster/client/src/KeymasterUI.js +++ b/services/keymaster/client/src/KeymasterUI.js @@ -1891,9 +1891,9 @@ function KeymasterUI({ keymaster, title, challengeDID, onWalletUpload }) { if (!newPass) { return; } - const confirm = window.prompt("Confirm new passphrase:"); - if (newPass !== confirm) { - window.alert("Passphrases do not match"); + const confirmPassphrase = window.prompt("Confirm new passphrase:"); + if (newPass !== confirmPassphrase) { + showError("Passphrases do not match"); return; } await keymaster.changePassphrase(newPass);