diff --git a/background.js b/background.js index ff82fbc..92a2d42 100644 --- a/background.js +++ b/background.js @@ -8,6 +8,17 @@ let state = { let popup_port = null // communication channel with popup +function send_state(state) +{ + popup_port.postMessage({type: 'state', data: state}) +} + +function show_error(error) +{ + console.error(error) + popup_port.postMessage({type: 'notification', data: error}) +} + function b32decode(text) { const up_text = text.toUpperCase() @@ -19,11 +30,13 @@ function b32decode(text) const char = up_text[index] if(char === '=') break - let value = char.charCodeAt() - 65 - if(value < 0) - value += 41 - if(value < 0 || value > 31) - throw `Incorrect Base32 char '${text[index]}' at index ${index}` + let value = char.charCodeAt() + if(value >= 65 && value <= 90) // char in [A- Z] + value -= 65 + else if(value >= 50 && value <= 55) // char in [2-7] + value -= 24 + else + throw `Incorrect Base32 char '${text[index]}' at index ${index}` if(lshift > 0) // next value is needed to complete the octet { @@ -50,8 +63,16 @@ async function setKey(password) const storage = await browser.storage.local.get() if(storage.entries !== undefined && storage.iv !== undefined && storage.salt !== undefined) { - state.iv = new Uint8Array(b32decode(storage.iv)) - state.salt = new Uint8Array(b32decode(storage.salt)) + try + { + state.iv = new Uint8Array(b32decode(storage.iv)) + state.salt = new Uint8Array(b32decode(storage.salt)) + } + catch(error) + { + show_error(error) + return + } } let encoder = new TextEncoder(); @@ -76,12 +97,23 @@ async function setKey(password) if(storage.entries !== undefined) restore(storage) else - popup_port.postMessage(state) + send_state(state) } // Decrypt entries saved in local storage async function restore(storage) { + let decoded_secret = null + try + { + decoded_secret = new Uint8Array(b32decode(storage.entries)) + } + catch(error) + { + show_error(error) + return + } + try { let decrypted = await window.crypto.subtle.decrypt( @@ -89,17 +121,16 @@ async function restore(storage) name: "AES-GCM", iv: state.iv }, - state.key, - new Uint8Array(b32decode(storage.entries)) + state.key, decoded_secret ); let decoder = new TextDecoder(); state.entries = JSON.parse(decoder.decode(decrypted)) - popup_port.postMessage(state) + send_state(state) } - catch (error) + catch(_error) { - console.error('Cannot decrypt entries: wrong password') + show_error('Cannot decrypt entries: wrong password') } } @@ -109,11 +140,9 @@ function connected(port) { if(message.command === 'init') { if(state.key === null) - popup_port.postMessage(state) + send_state(state) else - browser.storage.local.get().then((storage) => { - restore(storage) - }) + browser.storage.local.get().then((storage) => { restore(storage) }) } else if(message.command === 'key') setKey(message.password) @@ -123,8 +152,8 @@ function connected(port) { state.entries = [] } else - console.error(`Wrong message: ${message}`) + show_error(`Wrong message: ${message}`) }) - } +} - browser.runtime.onConnect.addListener(connected); \ No newline at end of file +browser.runtime.onConnect.addListener(connected); \ No newline at end of file diff --git a/popup.css b/popup.css index 51953cd..dbb5378 100644 --- a/popup.css +++ b/popup.css @@ -5,6 +5,7 @@ --highlight-bg-color: hsl(213, 10%, 28%); --fg-color: #ccc; --border-color: #888; + --error-bg-color: hsl(0, 38%, 30%); --img-filter: ; } } @@ -16,16 +17,23 @@ --highlight-bg-color: #ccc; --fg-color: #666; --border-color: #888; + --error-bg-color: hsl(0, 38%, 70%); --img-filter: invert(1); } } +* +{ + box-sizing: border-box; +} + body { background-color: var(--bg-color); color: var(--fg-color); max-height: 600px; margin: 0; font-size: 12px; + position: relative; } input { @@ -171,6 +179,30 @@ h2 { cursor: pointer; } +#notification { + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: 10; + display: flex; + flex-direction: row; + justify-content: space-between; + background-color: var(--error-bg-color); + font-size: 1.2em; + padding: 4px; + transform: translateY(-100%); + transition: transform 0.3s; +} + +#notification.show { + transform: translateY(0); +} + +#notification img { + height: 1em; +} + #password-container { padding: 1em; } diff --git a/popup.html b/popup.html index a06e4ae..0e165e0 100644 --- a/popup.html +++ b/popup.html @@ -6,6 +6,10 @@
+