forked from jsnbuchanan/crowd-funder-for-time-pwa
add encryption & decryption for the sensitive identity & mnemonic in SQL DB
This commit is contained in:
@@ -16,11 +16,11 @@ import {
|
||||
updateAccountSettings,
|
||||
updateDefaultSettings,
|
||||
} from "../db/index";
|
||||
import { Account } from "../db/tables/accounts";
|
||||
import { Account, AccountEncrypted } from "../db/tables/accounts";
|
||||
import { Contact } from "../db/tables/contacts";
|
||||
import * as databaseUtil from "../db/databaseUtil";
|
||||
import { DEFAULT_PASSKEY_EXPIRATION_MINUTES } from "../db/tables/settings";
|
||||
import { deriveAddress, generateSeed, newIdentifier } from "../libs/crypto";
|
||||
import { arrayBufferToBase64, base64ToArrayBuffer, deriveAddress, generateSeed, newIdentifier, simpleDecrypt, simpleEncrypt } from "../libs/crypto";
|
||||
import * as serverUtil from "../libs/endorserServer";
|
||||
import {
|
||||
containsHiddenDid,
|
||||
@@ -466,9 +466,17 @@ export function findAllVisibleToDids(
|
||||
export interface AccountKeyInfo extends Account, KeyMeta {}
|
||||
|
||||
export const retrieveAccountCount = async (): Promise<number> => {
|
||||
// one of the few times we use accountsDBPromise directly; try to avoid more usage
|
||||
const accountsDB = await accountsDBPromise;
|
||||
return await accountsDB.accounts.count();
|
||||
let result;
|
||||
const platformService = PlatformServiceFactory.getInstance();
|
||||
const dbResult = await platformService.dbQuery(`SELECT COUNT(*) FROM accounts`);
|
||||
result = dbResult.values[0][0] as number;
|
||||
|
||||
if (USE_DEXIE_DB) {
|
||||
// one of the few times we use accountsDBPromise directly; try to avoid more usage
|
||||
const accountsDB = await accountsDBPromise;
|
||||
result = await accountsDB.accounts.count();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const retrieveAccountDids = async (): Promise<string[]> => {
|
||||
@@ -513,13 +521,35 @@ export const retrieveAllAccountsMetadata = async (): Promise<Account[]> => {
|
||||
export const retrieveFullyDecryptedAccount = async (
|
||||
activeDid: string,
|
||||
): Promise<AccountKeyInfo | undefined> => {
|
||||
// one of the few times we use accountsDBPromise directly; try to avoid more usage
|
||||
const accountsDB = await accountsDBPromise;
|
||||
const account = (await accountsDB.accounts
|
||||
.where("did")
|
||||
.equals(activeDid)
|
||||
.first()) as Account;
|
||||
return account;
|
||||
let result: AccountKeyInfo | undefined = undefined;
|
||||
const platformService = PlatformServiceFactory.getInstance();
|
||||
const dbSecrets = await platformService.dbQuery(`SELECT secretBase64 from secret`);
|
||||
if (!dbSecrets || dbSecrets.values.length === 0 || dbSecrets.values[0].length === 0) {
|
||||
throw new Error("No secret found. We recommend you clear your data and start over.");
|
||||
}
|
||||
const secretBase64 = dbSecrets.values[0][0] as string;
|
||||
const secret = base64ToArrayBuffer(secretBase64);
|
||||
const dbAccount = await platformService.dbQuery(`SELECT * FROM accounts WHERE did = ?`, [activeDid]);
|
||||
if (!dbAccount || dbAccount.values.length === 0 || dbAccount.values[0].length === 0) {
|
||||
throw new Error("Account not found.");
|
||||
}
|
||||
const fullAccountData = databaseUtil.mapColumnsToValues(dbAccount.columns, dbAccount.values)[0] as AccountEncrypted;
|
||||
const identityEncr = base64ToArrayBuffer(fullAccountData.identityEncrBase64);
|
||||
const mnemonicEncr = base64ToArrayBuffer(fullAccountData.mnemonicEncrBase64);
|
||||
fullAccountData.identity = await simpleDecrypt(identityEncr, secret);
|
||||
fullAccountData.mnemonic = await simpleDecrypt(mnemonicEncr, secret);
|
||||
result = fullAccountData;
|
||||
|
||||
if (USE_DEXIE_DB) {
|
||||
// one of the few times we use accountsDBPromise directly; try to avoid more usage
|
||||
const accountsDB = await accountsDBPromise;
|
||||
const account = (await accountsDB.accounts
|
||||
.where("did")
|
||||
.equals(activeDid)
|
||||
.first()) as Account;
|
||||
result = account;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// let's try and eliminate this
|
||||
@@ -548,15 +578,25 @@ export const generateSaveAndActivateIdentity = async (): Promise<string> => {
|
||||
try {
|
||||
// add to the new sql db
|
||||
const platformService = PlatformServiceFactory.getInstance();
|
||||
const secrets = await platformService.dbQuery(`SELECT secretBase64 FROM secret`);
|
||||
if (secrets.values.length === 0 || secrets.values[0].length === 0) {
|
||||
throw new Error("No initial encryption supported. We recommend you clear your data and start over.");
|
||||
}
|
||||
const secretBase64 = secrets.values[0][0] as string;
|
||||
const secret = base64ToArrayBuffer(secretBase64);
|
||||
const encryptedIdentity = await simpleEncrypt(identity, secret);
|
||||
const encryptedMnemonic = await simpleEncrypt(mnemonic, secret);
|
||||
const encryptedIdentityBase64 = arrayBufferToBase64(encryptedIdentity);
|
||||
const encryptedMnemonicBase64 = arrayBufferToBase64(encryptedMnemonic);
|
||||
await platformService.dbExec(
|
||||
`INSERT INTO accounts (dateCreated, derivationPath, did, identity, mnemonic, publicKeyHex)
|
||||
`INSERT INTO accounts (dateCreated, derivationPath, did, identityEncrBase64, mnemonicEncrBase64, publicKeyHex)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
new Date().toISOString(),
|
||||
derivationPath,
|
||||
newId.did,
|
||||
identity,
|
||||
mnemonic,
|
||||
encryptedIdentityBase64,
|
||||
encryptedMnemonicBase64,
|
||||
newId.keys[0].publicKeyHex,
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user