Skip to content

Commit

Permalink
Create encrypted storage for beacon
Browse files Browse the repository at this point in the history
  • Loading branch information
ajinkyaraj-23 committed Dec 2, 2024
1 parent d681c1a commit dec7b39
Show file tree
Hide file tree
Showing 7 changed files with 466 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ VITE_DISABLE_TYPESCRIPT_CHECK=false
VITE_DISABLE_ESLINT_CHECK=false
# if you want to see the errors in the browser
VITE_ENABLE_CHECKS_OVERLAY=false

LOCAL_STORAGE_PASSWORD="umami-password-example"
4 changes: 2 additions & 2 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@umami/desktop",
"productName": "umami",
"version": "2.3.4",
"version": "2.3.5",
"author": "Trilitech <[email protected]>",
"description": "Tezos Desktop Wallet",
"homepage": "https://umamiwallet.com",
Expand Down Expand Up @@ -37,7 +37,7 @@
"theme": "chakra-cli tokens src/style/theme.ts"
},
"devDependencies": {
"@airgap/beacon-wallet": "^4.3.0",
"@airgap/beacon-wallet": "^4.3.1",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/preset-react": "^7.25.9",
Expand Down
1 change: 1 addition & 0 deletions packages/crypto/src/AES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const encrypt = async (data: string, password: string): Promise<Encrypted
};
};

// V1 - for backup/local storage , V2 - for transactions
type DecryptMode = "V1" | "V2";

export const TOO_MANY_ATTEMPTS_ERROR =
Expand Down
2 changes: 1 addition & 1 deletion packages/state/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
]
},
"dependencies": {
"@airgap/beacon-wallet": "^4.3.0",
"@airgap/beacon-sdk": "^4.3.1",
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.13.5",
"@emotion/styled": "^11.13.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/state/src/beacon/WalletClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { WalletClient as WalletClientClass } from "@airgap/beacon-wallet";
import { WalletClient as WalletClientClass } from "@airgap/beacon-sdk";
import { EncryptedBeaconStorage } from "./storage";
import { type Persistor } from "redux-persist";

export const WalletClient =
Expand All @@ -9,6 +10,7 @@ export const WalletClient =
name: "Umami",
iconUrl: "",
appUrl: "https://umamiwallet.com/",
storage: new EncryptedBeaconStorage(),
});

export const logout = (persistor: Persistor) =>
Expand Down
68 changes: 68 additions & 0 deletions packages/state/src/beacon/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// extend storage from beacon-types such that we encrypt the data we store and decrypt it when we retrieve it
// we can use the same encryption key for all data

import { Storage, type StorageKey, type StorageKeyReturnType } from "@airgap/beacon-sdk";
import { decrypt, encrypt, type EncryptedData } from "@umami/crypto";

// get a static password from enviornment variables

const local_storage_password: string = "umami-test-password-123";

export class EncryptedBeaconStorage extends Storage {
static async isSupported(): Promise<boolean> {
return typeof localStorage !== "undefined";
}

async get<K extends StorageKey>(key: K): Promise<StorageKeyReturnType[K]> {
const decryptData= localStorage.getItem(this.getPrefixedKey(key))?.split(",");
if (decryptData === undefined || local_storage_password === undefined) {
return undefined as StorageKeyReturnType[K];
}
const encryptedValue :EncryptedData= {
iv: decryptData[0],
salt: decryptData[1],
data: decryptData[2],
};
const decryptedValue = decrypt(encryptedValue, local_storage_password);
let result = JSON.parse(await decryptedValue) as StorageKeyReturnType[K];
console.log("Beacon encryption get:", key, result);
return result;

}

async set<K extends StorageKey>(key: K, value: StorageKeyReturnType[K]): Promise<void> {
console.log("Beacon encryption set:", key, value );
if (local_storage_password === undefined) {
return;
}
const stringValue = JSON.stringify(value);
const encryptedValue = await encrypt(stringValue, local_storage_password);
localStorage.setItem(this.getPrefixedKey(key),[encryptedValue.iv, encryptedValue.salt, encryptedValue.data].join(","));
}

async delete<K extends StorageKey>(key: K): Promise<void> {
localStorage.removeItem(this.getPrefixedKey(key));
}

async subscribeToStorageChanged(callback: (arg: {
eventType: "storageCleared" | "entryModified";
key: string | null;
oldValue: string | null;
newValue: string | null;
}) => {}): Promise<void> {
window.addEventListener("storage", (event) => {
if (event.storageArea === localStorage) {
callback({
eventType: event.key ? "entryModified" : "storageCleared",
key: event.key,
oldValue: event.oldValue,
newValue: event.newValue,
});
}
});
}

getPrefixedKey<K extends StorageKey>(key: K): string {
return `beacon:${key}`;
}
}
Loading

0 comments on commit dec7b39

Please sign in to comment.