Skip to content

Commit

Permalink
Merge pull request #21 from akopachov/ghi-19
Browse files Browse the repository at this point in the history
Implemented #19
  • Loading branch information
akopachov committed Sep 14, 2023
2 parents ef6df06 + 4f3abc4 commit 68db03d
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 2 deletions.
10 changes: 10 additions & 0 deletions src/electron.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ function createWindow() {
windowState.saveState(mainWindow);
});

mainWindow.webContents.on('render-process-gone', (_, detailed) => {
if (detailed.reason === 'crashed') {
mainWindow.webContents.reload();
}
});

return mainWindow;
}

Expand Down Expand Up @@ -90,4 +96,8 @@ app.on('window-all-closed', () => {
});
app.once('ready', () => autoUpdater.checkForUpdatesAndNotify());

process.on('uncaughtException', err => {
log.error('Unchaught exception happened', err);
});

Store.initRenderer();
46 changes: 46 additions & 0 deletions src/lib/import/aegis-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { TokenHashingAlgo } from '$models/token-hashing-algo';
import { TokenInfo } from '$models/token-info';
import { TokenLength } from '$models/token-length';
import { TokenSecretEncoding } from '$models/token-secret-encoding';

function tokenLengthFromAegis(num: number) {
if (num == 5) return TokenLength.FiveDigits;
if (num == 8) return TokenLength.EightDigits;
return TokenLength.SixDigits;
}

function nameFromAegis(issuer: string, account: string): string {
if (issuer && account) {
return `${issuer} (${account})`;
}

return account || issuer;
}

function tokenHashingAlgoFromAegis(str?: string) {
const strNorm = str?.toLowerCase()?.trim();
if (strNorm == TokenHashingAlgo.Sha256) return TokenHashingAlgo.Sha256;
if (strNorm == TokenHashingAlgo.Sha512) return TokenHashingAlgo.Sha512;
return TokenHashingAlgo.Sha1;
}

export function importFromAegisAuth(data: any) {
const entries = data?.db?.entries;
if (entries === null || !Array.isArray(entries)) {
throw Error('Invalid import data file');
}

return entries
.filter(f => f.type === 'totp')
.map(
m =>
new TokenInfo({
name: nameFromAegis(m.issuer, m.name),
secret: m.info.secret,
secretEncoding: TokenSecretEncoding.Base32,
duration: m.info.period,
length: tokenLengthFromAegis(m.info.digits),
hashingAlgo: tokenHashingAlgoFromAegis(m.info.algo),
}),
);
}
1 change: 1 addition & 0 deletions src/lib/import/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './google-auth';
export * from './aegis-auth';
14 changes: 12 additions & 2 deletions src/routes/import/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
</script>

<div class="flex h-max min-h-full">
<div class="flex mx-auto justify-center flex-col w-full max-w-sm">
<a class="btn variant-ghost btn-lg" href="/import/google">
<div class="flex mx-auto justify-center flex-col w-full max-w-sm gap-3">
<a class="btn variant-ghost btn-lg pb-3" href="/import/google">
<svg
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
Expand All @@ -25,5 +25,15 @@
</svg>
<span>Google Authenticator</span>
</a>
<a class="btn variant-ghost btn-lg" href="/import/aegis">
<svg class="w-12 h-12" viewBox="0 0 192 192" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="12"
d="M22 154 92.51 28.224c1.529-2.726 5.451-2.726 6.98 0L170 154M96 87l37 67m-37 0-18.5-33.5" />
</svg>
<span>Aegis Authenticator</span>
</a>
</div>
</div>
87 changes: 87 additions & 0 deletions src/routes/import/aegis/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<script lang="ts">
import log from 'electron-log';
import { FileDropzone } from '@skeletonlabs/skeleton';
import { CommonToastType, GlobalCommonToast } from '$stores/global-common-toast';
import { importFromAegisAuth } from '$lib/import';
import type { TokenInfo } from '$models/token-info';
import { goto } from '$app/navigation';
import { dataToQueryString } from '$lib/query-string-utils';
GlobalCommonToast.initialize();
let files: FileList;
async function processFiles() {
if (files.length <= 0) return;
let parsedTokens: TokenInfo[] = [];
let errorsFound = false;
for (let i = 0; i < files.length; i++) {
const file = files.item(i);
if (file) {
try {
const jsonContent = JSON.parse(await file.text());
parsedTokens.push(...importFromAegisAuth(jsonContent));
} catch (e) {
errorsFound = true;
log.error(e);
GlobalCommonToast.show(`Unable to import tokens from file ${file.path}`, CommonToastType.Error);
}
}
}
if (!errorsFound) {
if (parsedTokens.length > 0) {
const serializedParsedTokens = dataToQueryString(parsedTokens);
await goto(`/import/confirm?data=${serializedParsedTokens}`);
} else {
GlobalCommonToast.show('No tokens found', CommonToastType.Warning);
}
}
}
</script>

<div class="p-4">
<h4 class="h4">Import from Aegis Authenticator</h4>
<div class="mt-5 mb-5">
<ol class="list-decimal ml-4">
<li>Open Aegis Authenticator app on your phone</li>
<li>Tap the three-dots menu icon located on the top right corner</li>
<li>Select "Settings"</li>
<li>Select "Import & Export"</li>
<li>Select "Export"</li>
<li>As an "Export format" pick "Aegis (.JSON)"</li>
<li><strong>Uncheck "Encrypt the vault" checkbox</strong></li>
<li>Check "I understand the risk" checkbox</li>
<li>
Click "Share" or "Ok" button and <strong>
transfer the exported JSON file to this machine in the safest way possible
</strong>
</li>
<li>Drag & drop or select the exported JSON file in the area below</li>
</ol>
</div>
<div class="flex justify-center w-full">
<FileDropzone name="files" bind:files on:change={processFiles} accept=".json">
<svelte:fragment slot="lead">
<div class="flex justify-center">
<svg
class="w-9 h-9"
stroke-width="1.5"
fill="currentColor"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg">
<path
d="M515.5 366.1h230.6L461 80.8v230.7c0 30 24.5 54.6 54.5 54.6zM882 681.7l-98.8-98.8c-16.3-16.3-43.1-16.3-59.4 0L625 681.7c-16.3 16.3-16.3 43.1 0 59.4 16.3 16.3 43.1 16.3 59.4 0l27.1-27.1v193.9c0 23.1 18.9 42 42 42s42-18.9 42-42V714l27.1 27.1c16.3 16.3 43.1 16.3 59.4 0 16.4-16.4 16.4-43.1 0-59.4z" />
<path
d="M593.9 771.5c-31.2-31.2-31.2-82.4 0-113.6l91.2-91.2c3.1-4.8 6.7-9.3 10.8-13.5 14-14 31.9-21.7 50.3-23.1v-109H507.9c-56.4 0-102.1-45.7-102.1-102.1V80.8H190.3c-27.6 0-50.2 22.6-50.2 50.2v723c0 27.6 22.6 50.2 50.2 50.2h483V791.7c-27.3 7.9-58 1.2-79.4-20.2z" />
</svg>
</div>
</svelte:fragment>
<svelte:fragment slot="message">
<strong>Upload a file</strong>
or drag and drop
</svelte:fragment>
<svelte:fragment slot="meta">Only JSON allowed</svelte:fragment>
</FileDropzone>
</div>
</div>

0 comments on commit 68db03d

Please sign in to comment.