Skip to content

Commit

Permalink
Revert "feat: do not decrypt mnemonic for auth (#322)"
Browse files Browse the repository at this point in the history
This reverts commit 3110ff4.
  • Loading branch information
mateuszjasiuk committed Jul 10, 2023
1 parent 3110ff4 commit fe60293
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 169 deletions.
9 changes: 5 additions & 4 deletions apps/extension/src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@ import {
init as initKeyRing,
SDK_KEY,
PARENT_ACCOUNT_ID_KEY,
UtilityStore,
} from "./keyring";

const store = new IndexedDBKVStore(KVPrefix.IndexedDB);

const utilityStore = new IndexedDBKVStore<UtilityStore>(KVPrefix.Utility);
const activeAccountStore = new IndexedDBKVStore(KVPrefix.ActiveAccount);
// TODO: For now we will be running two stores side by side
const sdkStore = new IndexedDBKVStore(KVPrefix.SDK);
const extensionStore = new ExtensionKVStore(KVPrefix.LocalStorage, {
Expand Down Expand Up @@ -72,7 +71,9 @@ const { REACT_APP_NAMADA_URL = DEFAULT_URL } = process.env;
const sdkData: Record<string, string> | undefined = await sdkStore.get(
SDK_KEY
);
const activeAccount = await utilityStore.get<string>(PARENT_ACCOUNT_ID_KEY);
const activeAccount = await activeAccountStore.get<string>(
PARENT_ACCOUNT_ID_KEY
);

if (sdkData && activeAccount) {
const data = new TextEncoder().encode(sdkData[activeAccount]);
Expand All @@ -83,7 +84,7 @@ const { REACT_APP_NAMADA_URL = DEFAULT_URL } = process.env;
const keyRingService = new KeyRingService(
store,
sdkStore,
utilityStore,
activeAccountStore,
connectedTabsStore,
extensionStore,
defaultChainId,
Expand Down
116 changes: 35 additions & 81 deletions apps/extension/src/background/keyring/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import {
AES,
Argon2,
Argon2Params,
ByteSize,
Rng,
Salt,
VecU8Pointer,
} from "@anoma/crypto";
import { AES, Argon2, Argon2Params, ByteSize, Rng, Salt } from "@anoma/crypto";
import { AccountType, Bip44Path } from "@anoma/types";
import { Argon2Config } from "config";
import { CryptoRecord, KdfType, KeyStore } from "./types";
import { KdfType, KeyStore } from "./types";
import { readVecU8Pointer } from "@anoma/crypto/src/utils";

type CryptoArgs = {
Expand Down Expand Up @@ -39,10 +31,21 @@ export class Crypto {
text,
type,
} = args;
const saltInstance = Salt.generate();
const salt = saltInstance.as_string();
const { m_cost, t_cost, p_cost } = Argon2Config;
const argon2Params = new Argon2Params(m_cost, t_cost, p_cost);
const argon2 = new Argon2(password, salt, argon2Params);
const params = argon2.params();
const key = argon2.key();

const { params, key, iv, salt } = this.encryptionParams(password);
const cipherText = this.encryptWithAES(key, iv, text);
const crypto = this.cryptoRecord(cipherText, params, iv, salt);
const iv = Rng.generate_bytes(ByteSize.N12);
const aes = new AES(key, iv);
const encrypted = aes.encrypt(text);

saltInstance.free();
argon2.free();
aes.free();

return {
alias,
Expand All @@ -52,46 +55,32 @@ export class Crypto {
id,
parentId,
path,
crypto,
type,
};
}

private cryptoRecord(
cipherText: Uint8Array,
{ m_cost, t_cost, p_cost }: Argon2Params,
iv: Uint8Array,
salt: string
): CryptoRecord {
return {
cipher: {
type: "aes-256-gcm",
iv,
text: cipherText,
},
kdf: {
type: KdfType.Argon2,
params: {
m_cost,
t_cost,
p_cost,
salt,
crypto: {
cipher: {
type: "aes-256-gcm",
iv,
text: encrypted,
},
kdf: {
type: KdfType.Argon2,
params: {
m_cost: params.m_cost,
t_cost: params.t_cost,
p_cost: params.p_cost,
salt,
},
},
},
type,
};
}

public encryptAuthKey(password: string, uuid: string): CryptoRecord {
const { params, key, iv, salt } = this.encryptionParams(password);
const cipherText = this.encryptWithAES(key, iv, uuid);
return this.cryptoRecord(cipherText, params, iv, salt);
}

public decrypt(
crypto: CryptoRecord,
store: KeyStore,
password: string,
cryptoMemory: WebAssembly.Memory
): string {
const { crypto } = store;
const { cipher, kdf } = crypto;
const { m_cost, t_cost, p_cost, salt } = kdf.params;

Expand All @@ -102,46 +91,11 @@ export class Crypto {
const aes = new AES(newKey, cipher.iv);
const vecU8Pointer = aes.decrypt(cipher.text);
const decrypted = readVecU8Pointer(vecU8Pointer, cryptoMemory);
const plainText = new TextDecoder().decode(decrypted);
const phrase = new TextDecoder().decode(decrypted);

aes.free();
vecU8Pointer.free();

return plainText;
}

private encryptionParams(password: string): {
params: Argon2Params;
key: VecU8Pointer;
salt: string;
iv: Uint8Array;
} {
const saltInstance = Salt.generate();

const salt = saltInstance.as_string();
saltInstance.free();

const { m_cost, t_cost, p_cost } = Argon2Config;
const argon2Params = new Argon2Params(m_cost, t_cost, p_cost);
const argon2 = new Argon2(password, salt, argon2Params);
const params = argon2.params();
const key = argon2.key();
argon2.free();

const iv = Rng.generate_bytes(ByteSize.N12);

return { params, key, salt, iv };
}

private encryptWithAES(
key: VecU8Pointer,
iv: Uint8Array,
plainText: string
): Uint8Array {
const aes = new AES(key, iv);
const cipherText = aes.encrypt(plainText);
aes.free();

return cipherText;
return phrase;
}
}
51 changes: 12 additions & 39 deletions apps/extension/src/background/keyring/keyring.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { v5 as uuid } from "uuid";
import BigNumber from "bignumber.js";
import { v5 as uuid, v4 as uuidV4 } from "uuid";

import {
HDWallet,
Expand Down Expand Up @@ -32,8 +32,6 @@ import {
KeyStore,
ResetPasswordError,
DeleteAccountError,
CryptoRecord,
UtilityStore,
} from "./types";
import {
readVecStringPointer,
Expand Down Expand Up @@ -63,7 +61,6 @@ const getId = (name: string, ...args: (number | string)[]): string => {
export const KEYSTORE_KEY = "key-store";
export const SDK_KEY = "sdk-store";
export const PARENT_ACCOUNT_ID_KEY = "parent-account-id";
export const AUTHKEY_KEY = "auth-key-store";

const crypto = new Crypto();

Expand All @@ -86,7 +83,7 @@ export class KeyRing {
constructor(
protected readonly kvStore: KVStore<KeyStore[]>,
protected readonly sdkStore: KVStore<Record<string, string>>,
protected readonly utilityStore: KVStore<UtilityStore>,
protected readonly activeAccountStore: KVStore<string>,
protected readonly extensionStore: KVStore<number>,
protected readonly chainId: string,
protected readonly sdk: Sdk,
Expand Down Expand Up @@ -118,11 +115,11 @@ export class KeyRing {
}

public async getActiveAccountId(): Promise<string | undefined> {
return await this.utilityStore.get(PARENT_ACCOUNT_ID_KEY);
return await this.activeAccountStore.get(PARENT_ACCOUNT_ID_KEY);
}

public async setActiveAccountId(parentId: string): Promise<void> {
await this.utilityStore.set(PARENT_ACCOUNT_ID_KEY, parentId);
await this.activeAccountStore.set(PARENT_ACCOUNT_ID_KEY, parentId);

// To sync sdk wallet with DB
const sdkData = await this.sdkStore.get(SDK_KEY);
Expand All @@ -137,16 +134,12 @@ export class KeyRing {
): Promise<boolean> {
// default to active account if no account provided
const idToCheck = accountId ?? (await this.getActiveAccountId());
if (!idToCheck) {
throw new Error("No account to check password against");
}

const authKeys = await this.utilityStore.get<{
[id: string]: CryptoRecord;
}>(AUTHKEY_KEY);
if (authKeys) {
const mnemonic = await this._keyStore.getRecord("id", idToCheck);
// TODO: Generate arbitrary data to check decryption against
if (mnemonic) {
try {
crypto.decrypt(authKeys[idToCheck], password, this._cryptoMemory);
crypto.decrypt(mnemonic, password, this._cryptoMemory);
return true;
} catch (error) {
console.warn(error);
Expand Down Expand Up @@ -179,7 +172,7 @@ export class KeyRing {

for (const account of allAccounts) {
const decryptedSecret = crypto.decrypt(
account.crypto,
account,
currentPassword,
this._cryptoMemory
);
Expand Down Expand Up @@ -271,7 +264,6 @@ export class KeyRing {
});

await this._keyStore.append(mnemonicStore);
await this.generateAuthKey(id, password);
// When we are adding new top level account we have to clear the storage
// to prevent adding top level secret key to existing keys
this.sdk.clear_storage();
Expand All @@ -286,21 +278,6 @@ export class KeyRing {
return false;
}

public async generateAuthKey(
accountId: string,
password: string
): Promise<void> {
const id = uuidV4();
const authKey = crypto.encryptAuthKey(password, id);
const entries = await this.utilityStore.get<{ [id: string]: CryptoRecord }>(
AUTHKEY_KEY
);
await this.utilityStore.set(AUTHKEY_KEY, {
...entries,
[accountId]: authKey,
});
}

public deriveTransparentAccount(
seed: VecU8Pointer,
path: Bip44Path,
Expand Down Expand Up @@ -488,7 +465,7 @@ export class KeyRing {
const parentId = storedMnemonic.id;
try {
const phrase = crypto.decrypt(
storedMnemonic.crypto,
storedMnemonic,
password,
this._cryptoMemory
);
Expand Down Expand Up @@ -639,7 +616,7 @@ export class KeyRing {
let pk: string;

try {
pk = crypto.decrypt(account.crypto, this._password, this._cryptoMemory);
pk = crypto.decrypt(account, this._password, this._cryptoMemory);
} catch (e) {
throw new Error(`Could not unlock account for ${address}: ${e}`);
}
Expand Down Expand Up @@ -696,11 +673,7 @@ export class KeyRing {
if (!account) {
throw new Error(`Account not found.`);
}
const text = crypto.decrypt(
account.crypto,
this._password,
this._cryptoMemory
);
const text = crypto.decrypt(account, this._password, this._cryptoMemory);

// For shielded accounts we need to return the spending key as well.
const extendedSpendingKey =
Expand Down
5 changes: 2 additions & 3 deletions apps/extension/src/background/keyring/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
TabStore,
ResetPasswordError,
DeleteAccountError,
UtilityStore,
} from "./types";
import { syncTabs, updateTabStorage } from "./utils";
import { ExtensionRequester, getAnomaRouterId } from "extension";
Expand All @@ -38,7 +37,7 @@ export class KeyRingService {
constructor(
protected readonly kvStore: KVStore<KeyStore[]>,
protected readonly sdkStore: KVStore<Record<string, string>>,
protected readonly utilityStore: KVStore<UtilityStore>,
protected readonly accountAccountStore: KVStore<string>,
protected readonly connectedTabsStore: KVStore<TabStore[]>,
protected readonly extensionStore: KVStore<number>,
protected readonly chainId: string,
Expand All @@ -50,7 +49,7 @@ export class KeyRingService {
this._keyRing = new KeyRing(
kvStore,
sdkStore,
utilityStore,
accountAccountStore,
extensionStore,
chainId,
sdk,
Expand Down
Loading

0 comments on commit fe60293

Please sign in to comment.