Skip to content

Commit 8462563

Browse files
committed
Fix: remove Enter-key auto-save. PBKDF2 + AES-256-GCM encryption upgrade
1 parent a81f57c commit 8462563

2 files changed

Lines changed: 34 additions & 11 deletions

File tree

js/app.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,7 @@ window.Authenticator = window.Authenticator || {};
6161
Authenticator.showToast('Invalid secret key.', 'error');
6262
}
6363
});
64-
$.secretInput.addEventListener('keydown', e => {
65-
if (e.key === 'Enter') $.setSecretBtn.click();
66-
});
67-
$.issuerInput.addEventListener('keydown', e => {
68-
if (e.key === 'Enter') $.setSecretBtn.click();
69-
});
64+
7065

7166
// Preview copy
7267
$.otpDisplay.addEventListener('click', Authenticator.copyPreviewCode);

js/wallet.js

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,21 @@ window.Authenticator = window.Authenticator || {};
2323
const signer = provider.getSigner();
2424
const address = accounts[0];
2525

26-
const message = 'Authenticator Wallet Sync\n\nSign this message to encrypt and sync your 2FA accounts.\nWallet: ' + address + '\nTimestamp: ' + Date.now();
26+
const message = 'Authenticator Sync v2\nWallet: ' + address + '\nTimestamp: ' + Date.now();
2727
const signature = await signer.signMessage(message);
2828

29-
const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(signature));
30-
const key = await crypto.subtle.importKey('raw', hash, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt']);
29+
const salt = crypto.getRandomValues(new Uint8Array(16));
30+
const enc = new TextEncoder();
31+
const keyMaterial = await crypto.subtle.importKey('raw', enc.encode(signature), 'PBKDF2', false, ['deriveKey']);
32+
const key = await crypto.subtle.deriveKey(
33+
{ name: 'PBKDF2', salt, iterations: 600000, hash: 'SHA-256' },
34+
keyMaterial,
35+
{ name: 'AES-GCM', length: 256 },
36+
false,
37+
['encrypt', 'decrypt']
38+
);
39+
40+
Authenticator.wallet.salt = salt;
3141

3242
Authenticator.wallet.address = address;
3343
Authenticator.wallet.provider = provider;
@@ -81,10 +91,12 @@ window.Authenticator = window.Authenticator || {};
8191
combined.set(iv, 0);
8292
combined.set(new Uint8Array(encrypted), iv.length);
8393

94+
const saltB64 = btoa(String.fromCharCode.apply(null, Authenticator.wallet.salt));
8495
const base64 = btoa(String.fromCharCode.apply(null, combined));
8596
const payload = JSON.stringify({
86-
v: 1,
97+
v: 2,
8798
w: Authenticator.wallet.address,
99+
s: saltB64,
88100
d: base64
89101
});
90102

@@ -116,13 +128,29 @@ window.Authenticator = window.Authenticator || {};
116128
return false;
117129
}
118130

131+
let importKey = Authenticator.wallet.encryptionKey;
132+
if (data.v >= 2 && data.s) {
133+
const signature = await Authenticator.wallet.signer.signMessage(
134+
'Authenticator Sync v2\nWallet: ' + Authenticator.wallet.address + '\nTimestamp: ' + Date.now()
135+
);
136+
const salt = Uint8Array.from(atob(data.s), c => c.charCodeAt(0));
137+
const keyMaterial = await crypto.subtle.importKey('raw', new TextEncoder().encode(signature), 'PBKDF2', false, ['deriveKey']);
138+
importKey = await crypto.subtle.deriveKey(
139+
{ name: 'PBKDF2', salt, iterations: 600000, hash: 'SHA-256' },
140+
keyMaterial,
141+
{ name: 'AES-GCM', length: 256 },
142+
false,
143+
['encrypt', 'decrypt']
144+
);
145+
}
146+
119147
const combined = Uint8Array.from(atob(data.d), c => c.charCodeAt(0));
120148
const iv = combined.slice(0, 12);
121149
const encrypted = combined.slice(12);
122150

123151
const decrypted = await crypto.subtle.decrypt(
124152
{ name: 'AES-GCM', iv },
125-
Authenticator.wallet.encryptionKey,
153+
importKey,
126154
encrypted
127155
);
128156

0 commit comments

Comments
 (0)