diff --git a/src/libs/crypto/index.ts b/src/libs/crypto/index.ts index 9a884cee..b8ff2d57 100644 --- a/src/libs/crypto/index.ts +++ b/src/libs/crypto/index.ts @@ -32,7 +32,7 @@ export const newIdentifier = ( publicHex: string, privateHex: string, derivationPath: string, -): Omit => { +): IIdentifier => { return { did: DEFAULT_DID_PROVIDER_NAME + ":" + address, keys: [ diff --git a/src/libs/util.ts b/src/libs/util.ts index 70ae3d1c..c29a5cbd 100644 --- a/src/libs/util.ts +++ b/src/libs/util.ts @@ -42,6 +42,8 @@ import { createPeerDid } from "../libs/crypto/vc/didPeer"; import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer"; import { logger } from "../utils/logger"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; +import { sha256 } from "ethereum-cryptography/sha256"; +import { IIdentifier } from "@veramo/core"; export interface GiverReceiverInputInfo { did?: string; @@ -622,14 +624,12 @@ export const retrieveFullyDecryptedAccount = async ( return result; }; -export const retrieveAllAccountsMetadata = async (): Promise => { +export const retrieveAllAccountsMetadata = async (): Promise => { const platformService = PlatformServiceFactory.getInstance(); const dbAccounts = await platformService.dbQuery(`SELECT * FROM accounts`); const accounts = databaseUtil.mapQueryResultToValues(dbAccounts) as Account[]; let result = accounts.map((account) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { identity, mnemonic, ...metadata } = account; - return metadata as Account; + return account as AccountEncrypted; }); if (USE_DEXIE_DB) { // one of the few times we use accountsDBPromise directly; try to avoid more usage @@ -638,7 +638,14 @@ export const retrieveAllAccountsMetadata = async (): Promise => { result = array.map((account) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { identity, mnemonic, ...metadata } = account; - return metadata as Account; + // This is not accurate because they can't be decrypted, but we're removing Dexie anyway. + const identityStr = JSON.stringify(identity); + const encryptedAccount = { + identityEncrBase64: sha256(new TextEncoder().encode(identityStr)).toString(), + mnemonicEncrBase64: sha256(new TextEncoder().encode(account.mnemonic)).toString(), + ...metadata, + }; + return encryptedAccount as AccountEncrypted; }); } return result; @@ -648,9 +655,8 @@ export const retrieveAllAccountsMetadata = async (): Promise => { * Saves a new identity to both SQL and Dexie databases */ export async function saveNewIdentity( - identity: string, + identity: IIdentifier, mnemonic: string, - newId: { did: string; keys: Array<{ publicKeyHex: string }> }, derivationPath: string, ): Promise { try { @@ -666,7 +672,8 @@ export async function saveNewIdentity( } const secretBase64 = secrets.values[0][0] as string; const secret = base64ToArrayBuffer(secretBase64); - const encryptedIdentity = await simpleEncrypt(identity, secret); + const identityStr = JSON.stringify(identity); + const encryptedIdentity = await simpleEncrypt(identityStr, secret); const encryptedMnemonic = await simpleEncrypt(mnemonic, secret); const encryptedIdentityBase64 = arrayBufferToBase64(encryptedIdentity); const encryptedMnemonicBase64 = arrayBufferToBase64(encryptedMnemonic); @@ -675,13 +682,13 @@ export async function saveNewIdentity( const params = [ new Date().toISOString(), derivationPath, - newId.did, + identity.did, encryptedIdentityBase64, encryptedMnemonicBase64, - newId.keys[0].publicKeyHex, + identity.keys[0].publicKeyHex, ]; await platformService.dbExec(sql, params); - await databaseUtil.updateDefaultSettings({ activeDid: newId.did }); + await databaseUtil.updateDefaultSettings({ activeDid: identity.did }); if (USE_DEXIE_DB) { // one of the few times we use accountsDBPromise directly; try to avoid more usage @@ -689,12 +696,12 @@ export async function saveNewIdentity( await accountsDB.accounts.add({ dateCreated: new Date().toISOString(), derivationPath: derivationPath, - did: newId.did, - identity: identity, + did: identity.did, + identity: identityStr, mnemonic: mnemonic, - publicKeyHex: newId.keys[0].publicKeyHex, + publicKeyHex: identity.keys[0].publicKeyHex, }); - await updateDefaultSettings({ activeDid: newId.did }); + await updateDefaultSettings({ activeDid: identity.did }); } } catch (error) { logger.error("Failed to update default settings:", error); @@ -715,9 +722,8 @@ export const generateSaveAndActivateIdentity = async (): Promise => { deriveAddress(mnemonic); const newId = newIdentifier(address, publicHex, privateHex, derivationPath); - const identity = JSON.stringify(newId); - await saveNewIdentity(identity, mnemonic, newId, derivationPath); + await saveNewIdentity(newId, mnemonic, derivationPath); await databaseUtil.updateAccountSettings(newId.did, { isRegistered: false }); if (USE_DEXIE_DB) { await updateAccountSettings(newId.did, { isRegistered: false }); diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 1ba7dce1..bc1c352a 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -1356,18 +1356,7 @@ export default class AccountViewView extends Vue { * Processes the identity and updates the component's state. */ async processIdentity() { - let account: Account | undefined = undefined; - const platformService = PlatformServiceFactory.getInstance(); - const dbAccount = await platformService.dbQuery( - "SELECT * FROM accounts WHERE did = ?", - [this.activeDid], - ); - if (dbAccount) { - account = databaseUtil.mapQueryResultToValues(dbAccount)[0] as Account; - } - if (USE_DEXIE_DB) { - account = await retrieveAccountMetadata(this.activeDid); - } + const account = await retrieveAccountMetadata(this.activeDid); if (account?.identity) { const identity = JSON.parse(account.identity as string) as IIdentifier; this.publicHex = identity.keys[0].publicKeyHex; @@ -1375,8 +1364,10 @@ export default class AccountViewView extends Vue { this.derivationPath = identity.keys[0].meta?.derivationPath as string; await this.checkLimits(); } else if (account?.publicKeyHex) { + // use the backup values in the top level of the account object this.publicHex = account.publicKeyHex as string; this.publicBase64 = Buffer.from(this.publicHex, "hex").toString("base64"); + this.derivationPath = account.derivationPath as string; await this.checkLimits(); } } diff --git a/src/views/ImportAccountView.vue b/src/views/ImportAccountView.vue index fcf04385..c328505d 100644 --- a/src/views/ImportAccountView.vue +++ b/src/views/ImportAccountView.vue @@ -165,7 +165,7 @@ export default class ImportAccountView extends Vue { await accountsDB.accounts.clear(); } } - saveNewIdentity(JSON.stringify(newId), mne, newId, this.derivationPath); + await saveNewIdentity(newId, mne, this.derivationPath); this.$router.push({ name: "account" }); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err: any) { diff --git a/src/views/ImportDerivedAccountView.vue b/src/views/ImportDerivedAccountView.vue index 2561d659..090ead41 100644 --- a/src/views/ImportDerivedAccountView.vue +++ b/src/views/ImportDerivedAccountView.vue @@ -20,18 +20,18 @@ Will increment the maximum known derivation path from the existing seed.

-

+

Choose existing DIDs from same seed phrase to compute derivation.

  • @@ -41,8 +41,8 @@ class="fa-fw text-slate-400 text-xl mr-3" > -
    - {{ dids.join(",") }} +
    + {{ dids.map((d) => d.did).join(" ") }}
  • @@ -69,6 +69,7 @@