Вийшла версія Authenticator 1.13.0. Що нового

Додати в Chrome

Як це працює

Технічний огляд для тих, хто перевіряє безпеку. Усе викладене можна звірити з вихідним кодом — зокрема й те, що нас не прикрашає: ми це називаємо, а не оминаємо.

Архітектура

Бекенду немає. Це розширення Chrome на Manifest V3, яке генерує коди TOTP/HOTP локально за допомогою OTPAuth. Ми не тримаємо серверів, не заводимо облікових записів і не маємо каналу, яким дані користувача могли б до нас потрапити.

Немає сервера — немає й ключового матеріалу на боці сервера, депонування ключів чи будь-якого шляху відновлення, який контролювали б ми. Якщо користувач забув пароль і втратив код відновлення, ми не зможемо зарадити — так задумано.

Криптографія

Захист паролем необов'язковий і типово вимкнений. Коли його ввімкнено:

Шифр
AES-256-GCM, випадковий 96-бітний IV для кожного запису й кожного перезапису
Вироблення ключа
PBKDF2-HMAC-SHA256, 600 000 ітерацій, випадкова 128-бітна сіль (за рекомендаціями OWASP)
Майстер-ключ
256 біт, із crypto.getRandomValues, генерується один раз; пароль лише огортає його
Відбитки
HMAC-SHA256 на підключі, виведеному через HKDF; потрібні для зведення записів між пристроями
Зберігання розблокованого ключа
chrome.storage.session — лише в пам'яті, ніколи не пишеться на диск, очищається при закритті браузера, недосяжний для content-скриптів
Автоблокування
За кожного відкриття / через 5, 15, 60 хвилин бездіяльності / до закриття браузера
Реалізація
Тільки WebCrypto. Жоден примітив не написано вручну, жодної криптобібліотеки в збірці немає.

Чому ключів два рівні

Дані ніколи не шифруються ключем, виведеним із пароля, безпосередньо. Записи шифрує випадковий майстер-ключ; вивід PBKDF2 лише огортає цей майстер-ключ. Звідси два наслідки, і обидва важливі:

  • Зміна пароля переписує 32 байти замість перешифрування кожного запису, кожної резервної копії та кожного експорту. Саме на масовому перезаписі сховища й втрачають дані.
  • 160-бітний код відновлення може незалежно огорнути той самий майстер-ключ, тож забутий пароль не вирок. Код показується один раз, його треба ввести назад для підтвердження, і він змінюється після кожного використання. На диск нічого не пишеться, поки користувач його не підтвердив.

Що шифрується, а що ні

Коли захист паролем увімкнено, шифрується весь запис облікового запису, крім ідентифікатора та відбитка — зокрема й назва сервісу, тож із викраденого профілю не зрозуміти, обліковими записами яких сервісів володіє користувач. Під час увімкнення розширення шифрує записи, перевіряє їх розшифруванням і порівнянням і лише тоді видаляє всі копії у відкритому вигляді: з локального сховища браузера, із синхронізації та з усіх семи ротованих знімків резервних копій.

Кажемо прямо, бо для вашої оцінки це суттєво:

  • Якщо захист паролем вимкнено, облікові записи зберігаються незашифрованими і, якщо ввімкнено синхронізацію Chrome, реплікуються через власний обліковий запис Google користувача. До нас вони не потрапляють ніколи, але Google їх зберігає. Синхронізацію можна вимкнути — це заразом видалить і те, що там уже є.
  • Історія використання за сайтами — який обліковий запис застосовується на якому домені — зберігається локально й, поки збирається, сховищем не захищена. Увімкнення захисту паролем її видаляє; її також можна вимкнути окремо.

Модель загроз

Захищає від

  • Викрадення або копіювання каталогу профілю браузера
  • Зловмисних програм-стилерів, які вивантажують дані браузера цілком
  • Фізичного доступу до залишеного без нагляду комп'ютера
  • Потрапляння записів облікових записів до Google через синхронізацію Chrome
  • Втрати чи викрадення файлу резервної копії (експорт під паролем)

Не захищає від

  • Зловмисного коду, що працює від імені користувача, поки сховище розблоковане
  • Кейлогера, який перехоплює пароль під час введення
  • Скомпрометованого браузера чи операційної системи
  • Зламу самих сервісів, для яких призначені коди
  • Незашифрований експорт, який ви самі вирішили зберегти, — звичайний JSON, посилання otpauth:// чи CXF читає будь-хто, хто відкриє файл

Коротко: це захищає дані у стані спокою. Пристрій, який під час роботи вже перебуває під контролем зловмисника, так захистити не можна — і ми цього не обіцяємо.

Дозволи

Маніфест оголошує п'ять дозволів і жодного дозволу на хости:

storage
Облікові записи й налаштування в локальному сховищі, розблокований ключ у session storage і необов'язкова копія для синхронізації
activeTab
Читає ім'я хоста активної вкладки, щоб підсвітити відповідний обліковий запис, і робить знімок вкладки, коли користувач сканує QR-код з екрана
contextMenus
Додає пункт «Вставити код 2FA» до контекстного меню, і лише на редагованих полях сторінок http(s)
scripting
Впроваджує одну функцію, яка вписує код у поле, — для однієї вкладки й одного виклику, лише після вибору цього пункту меню
sidePanel
Відкриває застосунок у бічній панелі Chrome, якщо обрано цей режим; доступу до сторінок не дає

Немає немає content-скриптів, немає дозволів tabs, cookies чи webRequest і немає web-accessible resources. Нічого нашого не існує на сторінці, доки ви не попросите там код; те, що тоді виконується, впроваджується для тієї однієї вкладки й того одного виклику, за дозволом, який дає ваш власний клік, і не лишає по собі нічого.

Камера

Сканування QR-коду камерою працює на сторінці розширення, відкритій у вкладці, а не у спливному вікні: popup знищується, щойно втрачає фокус, а запит дозволу саме це й робить. Для цього не потрібен дозвіл у маніфесті: використовується штатний запит камери браузера, який видається на origin розширення та відкликається в налаштуваннях сайту, і він ніколи не з'являється, доки користувач не відкриє сканер. Відео декодується локально, нікуди не передається й не зберігається.

Мережеві запити

Перевірка годинника — єдиний запит, який розширення робить самостійно; усе інше нижче стається тому, що користувач на це натиснув. Manifest V3 забороняє віддалений код, і ніщо з переліченого не передає ні облікових записів, ні секретних ключів, ні згенерованих кодів. Повний перелік:

ХостКолиПередає дані користувача?
time.akamai.com
timeapi.io
cloudflare.com
Перевірка розходження годинника, кешується; якщо жодне джерело недоступне, про це сказано в налаштуваннях. Зі збитим годинником TOTP ламається.Ні
authenticator.shСторінка привітання під час встановлення; сторінка зворотного зв'язку під час видалення; сторінки довідки та підтримки, коли їх відкривають із вікна розширення.Ні (звичайні логи вебсервера)
chromewebstore.google.comСторінка в магазині, відкривається у вкладці лише за кліком: форма відгуку — з пропозиції оцінити, наш менеджер паролів — із банера крос-промо.Ні (для Google це звичайний захід на сторінку магазину)
authenticator.featurebase.appПублічна дошка побажань, відкривається у вкладці за посиланням пропозиції нової функції на панелі підтримки.Лише те, що користувач там опублікує. Сторонній сервіс зі своїми умовами.

Ні шрифти, ні скрипти, ні стилі, ні зображення не завантажуються зі сторонніх хостів. Усе потрібне для відображення інтерфейсу лежить усередині пакета.

Як перевірити те, що ми публікуємо

Нічого з переліченого не треба брати на віру. Розширення має відкритий код, і кожен реліз відтворюваний:

  1. Завантажте опублікований .crx з Chrome Web Store і розпакуйте його
  2. Перемкніться на відповідний git-тег
  3. Виконайте npm ci && npm run build на Node 20 LTS
  4. Порівняйте отриманий dist/ з розпакованим пакетом

SHA-256 для кожного файлу в зібраному dist/ публікується з кожним релізом на GitHub у вигляді SHA256SUMS-v<version>.txt, у форматі sha256sum — тож крок 4 зводиться до одного запуску sha256sum -c. Розбіжності мають обмежуватися порядком файлів усередині архівів і пробілами в мініфікованому виводі на різних патч-версіях Node.

Залежностей у рантаймі свідомо мало — OTPAuth, React, jsQR, Zustand, Framer Motion і Lucide — усі зафіксовані закомміченим lock-файлом. SBOM у форматі CycloneDX надаємо на запит.

Переглянути вихідний код

Чого в нас немає

Ми невеликий незалежний розробник. Якщо щось із переліченого для вашого процесу обов'язкове, краще дізнатися про це зараз, а не на третьому тижні оцінювання:

  • Немає сертифікації SOC 2, ISO 27001 чи аналогічної
  • Незалежний пентест досі не замовлявся
  • Немає платної програми bug bounty

Натомість ми пропонуємо повну прозорість вихідного коду, перевірювану збірку, мінімальний набір дозволів і відсутність серверної інфраструктури, яка взагалі могла б зберігати ваші дані.

Як з нами зв'язатися

Повідомлення про вразливості та питання щодо безпеки: security@authenticator.sh. Політика розкриття, межі застосування, строки відповіді й умови safe harbour — на сторінці політики безпеки; що зберігається і що залишає пристрій — у політиці конфіденційності.

Ми готові заповнити письмову анкету оцінювання постачальника або розібрати код разом із вашою командою безпеки.

З усього, що не стосується безпеки — встановлення, відновлення доступу, питання оплати під час розгортання — див. підтримку. Будь ласка, не надсилайте туди повідомлень про вразливості: ця скринька не вважається конфіденційною.