dimhold.by
← Статьи

Простой классификатор назвал клавишу по звуку 99 раз из 100. Обученный на тишине между нажатиями, он всё равно назвал её 39 раз

Когда речь заходит о звуке клавиатуры, в голове у меня сидит одно число: 95%. В 2023 году Харрисон, Тореини и Мехрнежад положили iPhone рядом с MacBook Pro и обучили нейросеть на звуке клавиш. Она угадала 95% нажатий и 93% на записи Zoom, сделанной через микрофон самого ноутбука. В 2025 году Спата с соавторами получили 98,3% на тех же данных MacBook, потом записали механическую клавиатуру и сообщили о 99% на ней. У меня есть небольшой инструмент earshot, он слушает микрофон и переводит речь в текст. Тот же микрофон слышит каждую клавишу, которую я нажимаю. Про 95% я читал несколько раз и ни разу не спросил, на чём именно это мерили. Оба датасета открыты под лицензией MIT, поэтому в этот раз я их скачал и посмотрел.

Как устроен замер

Оба набора устроены одинаково. 36 клавиш, цифры и буквы. Каждая клавиша записана отдельным файлом WAV, в нём 25 нажатий подряд примерно раз в секунду. У Харрисона 2 записи одного и того же MacBook. Одна сделана телефоном, лежащим на салфетке из микрофибры, другая через Zoom с частотой 32 кГц с шумоподавлением на минимуме. Набор KAD от Спаты это механическая клавиатура и смартфон в 17 см от неё, плюс 10 паролей, набранных клавиша за клавишей, каждый своей записью.

Я хотел посмотреть, сколько возьмёт простая модель, поэтому без глубокой сети. Python 3.12, numpy 2.5.3, scipy 1.18.1, scikit-learn 1.9.0 на 4 ядрах. Каждое нажатие вырезается по порогу энергии, который подстраивается, пока в файле не найдётся ровно 25 нажатий. Потом 330 мс звука превращаются в логарифмическую мел-спектрограмму из 64 полос и на неё смотрит логистическая регрессия. Случайное угадывание при 36 клавишах даёт 2,8%.

Для проверки я делил нажатия по их месту в файле: нажатия с 0 по 4 в одном блоке, с 5 по 9 в следующем и так далее. При случайном разбиении у большинства тестовых нажатий соседи по времени попали бы в обучение. Здесь сосед в обучении есть только у нажатий на краю блока.

Вышло 92,4% на MacBook через телефон, 84,6% через Zoom и 99,3% на механической клавиатуре. Линейная модель без аугментации оказалась в пределах 3 пунктов от сети Харрисона на записи с телефона. На механической клавиатуре она сравнялась с 99% у Спаты. Этого я не ждал. На Zoom она отстала на 8 пунктов. На записи с телефона Спата с соавторами получили 98,3%, на 6 пунктов больше моего. В статьях данные делили иначе, так что сравнение грубое.

Где я перестал верить

Потом я ещё раз посмотрел на устройство файлов и меня это насторожило. Каждая клавиша живёт в своей записи. Допустим, телефон немного сдвинулся между записью a и записью b. Тогда классификатор может выучить файл вместо клавиши. Проверка выше этого не заметит, потому что тестовые нажатия берутся из тех же файлов.

Поэтому я обучил ту же модель на тишине. От каждого нажатия я взял 200 мс, которые начинаются через 400 мс после него. Звук там уже на 24–36 дБ тише нажатия. И спросил, какой клавише принадлежит этот кусок тишины. На MacBook через телефон тишина назвала клавишу в 29,4% случаев, через Zoom в 16,1%, на механической клавиатуре в 39,4%. Это в 6–14 раз выше случайного уровня.

Самой записи, без нажатия, хватает, чтобы назвать клавишу. Классификатор на нажатиях, возможно, тоже этим пользуется. Насколько, по этим файлам я сказать не могу.

доля нажатий, где клавиша названа верно MacBook Pro iPhone рядом нажатие 92,4% только тишина 29,4% MacBook Pro запись Zoom нажатие 84,6% только тишина 16,1% механическая телефон в 17 см нажатие 99,3% только тишина 39,4% пароли 77% наугад 2,8%
Тишина это 200 мс, которые начинаются через 400 мс после нажатия, когда звук нажатия по большей части затих. Каждая клавиша в этих датасетах лежит своим файлом, поэтому тишина, скорее всего, называет клавишу через запись. Пароли это 100 нажатий внутри 10 слов, проверка, где файл помочь не может.

Пароли KAD это проверка, в которой файл помочь не может. Там клавиши идут друг за другом внутри одной записи. Я обучил модель на всех 900 нажатиях из файлов клавиш и проверил на 100 нажатиях внутри 10 паролей. Сколько символов в каждом пароле, я заранее сообщил коду, который вырезает нажатия. Верными оказались 77 из 100. В 93 из 100 верная клавиша была в первой пятёрке. Целиком угадался 1 пароль из 10, baseball47. Хуже всех вышел position90, услышанный как ppsvtnpk00.

пароли KAD: что набрано и что услышано набрано услышано верно в пятёрке b a s e b a l l 4 7 b a s e b a l l 4 7 10/10 10/10 c u l t u r a l 1 2 c u l t u r a l 1 0 9/10 10/10 f r a g r a n t 3 4 f r a l r a n t 3 4 9/10 10/10 f r i e n d l y 5 6 f z k e n d l y 5 6 8/10 9/10 g r a t e f u l 1 0 l z n z e f u l 1 0 6/10 9/10 h a r d s h i p 3 8 h a r d s h i l 3 7 8/10 10/10 i d e o l o g y 7 8 i d e l k p g y 7 3 6/10 7/10 n o m i n a t e 2 9 n o m i n a t e x 9 9/10 10/10 p o s i t i o n 9 0 p p s v t n p k 0 0 4/10 9/10 s u p p r e s s 5 6 s u p n r e s x 5 6 8/10 9/10 77/100 93/100
Обучение на 900 нажатиях из файлов клавиш, проверка на паролях. Выделены неверно угаданные символы.

Из 23 неверных догадок 10 попали на физического соседа верной клавиши. Случайная пара клавиш на этой раскладке оказывается соседней в 13% случаев. Со словарём это полезный список кандидатов, но для пароля с цифрами в конце всё равно нужно 10 верных догадок подряд.

Спата с соавторами сделали похожую проверку, на 8 паролях, записанных позже на той же клавиатуре. Их сеть получила в среднем 89,1%. Их паролей в открытом наборе нет, поэтому напрямую сравнить я не могу, но это на 12 пунктов выше моих 77. В статье Харрисона такой проверки нет.

Где ломается

Другая запись той же клавиатуры. Я обучил модель на записи с телефона и проверил на записи Zoom, тот же MacBook и тот же человек за клавиатурой. Вышло 6,3%. Обратное направление дало 4,9%. Я думал, что причина в разной полосе частот: Zoom на 32 кГц против 44,1 кГц у телефона. Поэтому я оставил только мел-полосы ниже 8 кГц и вычел из каждой записи её средний логарифмический мел-спектр, это вроде грубого эквалайзера. Лучшее, что из этого вышло, 12%, в 4 раза выше случайного. Здесь меняются сразу три вещи: микрофон, сеанс записи и обработка Zoom. Разделить их я не могу. 92% и 85% на первом графике это 2 отдельные модели, каждая обучена на своей записи.

Шум. Здесь я сначала ошибся. Я добавил белый шум на 30 дБ тише нажатия и модель MacBook упала до случайного угадывания. Я какое-то время искал ошибку в коде шума, прежде чем сравнил уровни по полосам. Большая часть звука комнаты в записи телефона приходится на нижние полосы. Выше 1,1 кГц там так тихо, что даже шум на 60 дБ тише нажатия громче комнаты. Так в 47 полосах из 64. Когда последние 5 нажатий каждого файла отложены на проверку, у модели было 88% на чистых нажатиях, 43% при 60 дБ и 5,6% при 50 дБ. Я предполагаю, что она опирается на эти почти беззвучные верхние полосы.

Тогда я добавил тот же шум того же уровня и в обучающие нажатия. Модель MacBook держит 86% при 60 дБ, 61% при 30 дБ и 26% при 0 дБ, где шум так же громок, как само нажатие. Механическая клавиатура остаётся на 97% даже при 0 дБ. Каждая из этих моделей знала уровень шума заранее.

белый шум, добавленный к тестовым нажатиям 0% 25% 50% 75% 100% без шума 60 50 40 30 20 10 0 дБ, насколько шум тише нажатия MacBook, обучен с шумом MacBook, обучен без шума механическая, обучена с шумом механическая, обучена без шума
Проверка на последних 5 нажатиях каждого файла клавиши, обучение на первых 20. Уровень шума отсчитан от мощности первых 100 мс каждого нажатия. Пунктирная горизонталь это случайное угадывание, 2,8%.

Обучающие данные. Всё это требует размеченных нажатий именно этой клавиатуры именно в этом месте. На тех же отложенных нажатиях 1 размеченное нажатие на клавишу дало модели MacBook 11%, 5 нажатий 41%, 20 нажатий 88%. Механической клавиатуре нужно меньше: 50% с 1 нажатия и 89% с 5. Кто-то должен сначала нажать каждую клавишу под запись или атакующему придётся разметить нажатия другим способом. Работы, где это делают без разметки, используют языковую модель. Это отдельная задача и я её не повторял.

Чего я не проверял

Я не записывал свою клавиатуру. Замер шёл на сервере без микрофона, так что всё выше это 2 открытых датасета и 3 записи. В наборе Харрисона печатал один человек, про KAD не сказано. Я не пробовал глубокие сети из статей, так что перенос между записями с ними может выйти лучше. Я не пробовал печатать в обычном темпе, где нажатия накладываются, потому что моей нарезке нужно 200 мс между нажатиями. На записи MacBook в окне тишины звук ещё затухает, так что часть из этих 29% может приходиться на звук самой клавиши. Проверка на паролях от этого не зависит. Каждое число здесь получено за 1 прогон. Мои модели детерминированы, а генератор шума запускается с фиксированным зерном.

Для меня итог скромнее заголовка. Звук клавиши действительно выдаёт клавишу. На проверке паролями моя линейная модель получила 77 из 100, а сеть Спаты 89,1% на своих. Но в обоих случаях это та же клавиатура, та же комната и тот же микрофон, что и при обучении. С моей моделью другая запись того же MacBook опускает результат до 5 или 6%. Какая часть из 95% на MacBook пришла из файла, по этому датасету я сказать не могу.