Расшифровка создана автоматически и отредактирована с помощью ИИ для удобства чтения, поэтому возможны ошибки.
(00:00:04) Сергей Тихомиров: Всем привет! С вами снова подкаст «Базовый Блок», подкаст про блокчейн. У микрофона Сергей Тихомиров, и сегодня у нас в гостях Кирилл Пименов. Привет!
(00:00:14) Кирилл Пименов: Привет!
(00:00:15) Сергей Тихомиров: Кирилл — CEO компании Kalapaja, которая разрабатывает, в числе прочего, хардверные кошельки Kampela, а также платёжную систему Kalatori. Сегодня поговорим в основном про кошелёк, хотя и про систему тоже.
(00:00:32) Сергей Тихомиров: Прежде чем начнём, хочу поблагодарить тех, кто поддерживает наш подкаст — наших патронов на Patreon и Boosty. Спасибо вам большое. Заходите и поддерживайте нас, если вам нравится то, что мы делаем.
(00:00:40) Сергей Тихомиров: А также мы говорим спасибо нашим спонсорам. Fluence — облачная платформа на базе децентрализованной инфраструктуры, которая даёт более дешёвую и отказоустойчивую альтернативу традиционным облачным решениям, таким как AWS, DigitalOcean или Hetzner. С помощью Fluence вы получаете доступ к глобальной сети независимых провайдеров, можете быстро запускать виртуальные серверы и разворачивать рабочие нагрузки по всему миру. При этом вы значительно снижаете расходы и не зависите от одного провайдера. Спасибо Fluence!
(00:01:16) Сергей Тихомиров: Также нас поддерживает Zerion. Zerion API — мощный инструмент для Web3-разработчиков. С его помощью можно в реальном времени получать данные о кошельках, токенах, DeFi-позициях и NFT на более чем 24 блокчейнах, включая Ethereum и Solana. API предоставляет детальные человекочитаемые транзакции, мультичейн, uptime 99.9%, масштабируемость свыше 1000 запросов в секунду. API Zerion используют такие компании, как Uniswap, OpenSea, WalletConnect, Rainbow Wallet и другие. Спасибо Zerion!
(00:01:48) Сергей Тихомиров: Нас также поддерживает 1inch. На долю 1inch приходится около 60% рынка DeFi-агрегации и более 1 миллиарда долларов оборотов в сутки. 1inch уже проводит кроссчейн-свопы между Ethereum, Base, zkSync и другими EVM-сетями. Кроссчейн Solana — в финальной стадии. Профи оценят Pathfinder — топовый алгоритм 1inch, который помогает эффективно трейдить. Подключайтесь через API на 1inch.dev или прямо в интерфейсе 1inch.io.
(00:02:13) Сергей Тихомиров: И last but not least, нас поддерживает GOSH, кор-разработчик блокчейна Acki Nacki, основанного на новом протоколе, который достигает консенсуса за две итерации — самым быстрым из теоретически возможных. GOSH готовится к запуску mainnet в ближайшие месяцы. В коммьюнити уже более 4 миллионов участников. Заключены контракты, партнёрство с Oracle и Amper Computing. Основные направления развития — мобильный гейминг, биодиверсити-активы, мемкоины и DePIN. Большое спасибо GOSH, спасибо всем спонсорам и нашим патронам.
(00:02:38) Сергей Тихомиров: Небольшое дополнение, записанное уже после основной записи этого выпуска. Выпуск получился довольно объёмным, поэтому мы решили разбить его на две части. В первой части, в этом выпуске, мы поговорим в основном про хардверный сайнер Kampela. В продолжении, в следующем выпуске, мы обсудим некоторые другие аспекты проекта Kampela, но главным образом сосредоточимся на платёжной системе Kalatori, а также на ценностях шифропанка и на том, куда идёт наша любимая блокчейн-индустрия в целом.
(00:03:13) Сергей Тихомиров: Кирилл, давай начнём. Я посмотрел архив нашего подкаста и увидел, что ты был у нас в гостях последний раз аж в 2020 году, когда у нас были дебаты о governance децентрализованных проектов с Глебом Науменко. Много воды утекло с тех пор. Может, вкратце расскажешь, что поменялось в твоей профессиональной жизни с тех пор, а потом мы углубимся в детали.
(00:03:36) Кирилл Пименов: Самое важное — в конце 2022-го, начале 2023-го года я ушёл из Parity на вольные хлеба и делаю несколько своих проектов, а также по мере сил помогаю проектам, которым нужен человек, который с 2017 года много занимается именно прикладной безопасностью и opsec’ом блокчейна. Сейчас как раз это выливается в запуск новой штуки, которую я придумал, и платёжки.
(00:04:02) Кирилл Пименов: И в этом смысле хочу сказать слушателям: я пять лет не был здесь, не разговаривал с вами через этот подкаст — что вы сделали для хип-хопа, что вы сделали для идеального киберпанка и шифропанка? В целом всё идёт как-то печально, и я буду здесь голосом человека, который расстраивается, насколько быстро имеющиеся денежные структуры кооптируют былых идеалистов в то, чтобы делать прагматические, но не меняющие статус-кво вещи. Вот такой фундаментальный тейк.
(00:04:44) Сергей Тихомиров: А что тебе кажется самым расстраивающим, разочаровывающим или настораживающим за последние несколько лет в этом направлении?
(00:04:53) Кирилл Пименов: Не знаю, как выбрать одно «самое настораживающее», но был опыт, от которого я сгорел совсем — EthCC в Каннах в этом году. У меня проекты предполагают венчурное финансирование, я разговариваю с венчурами, подхожу к одному и говорю: мы придумали, как делать такую штуку — ровно то, что у вас заявлено, стейблкоин, payments для e-commerce, давай разговаривать. Он: «Нет, нам нужны только абсолютно regulatory compliant». Я: «Я придумал, как нам не делать KYC и быть regulatory compliant». «Нет». Через четыре-пять итераций выяснилось, что его понимание regulatory compliant — они сейчас напишут законы так, что все, в кого они их не проинтегрировали, окажутся за бортом.
(00:05:40) Кирилл Пименов: Это прямо данное мне в кинестетических ощущениях кооптирование: имеющиеся структуры власти и денег сливаются со всем, что строят шифропанки, и получается — кто кого обыграет? Шифропанк со своими кодиками онлайн или человек, который тридцать лет строит карьеру на том, что при помощи регуляторики говорит кому что можно, а кому ничего нельзя?
(00:06:07) Кирилл Пименов: И это печально, что все ведутся, что многие проекты выпускают эти несчастные карточки Visa, Mastercard с обеспечением криптой. Казалось бы, весь смысл в том, чтобы этого не делать — мы изобрели альтернативу Visa. Пятнадцать лет прошло с выпуска статьи Сатоши, и мы радостно бросаемся в объятия Mastercard, потому что не смогли сделать удобнее. В некотором смысле я не могу Молоха обвинять в том, что он Молох, не могу обвинять государственные суперструктуры в том, что они пытаются сохранить и преумножить свою власть, банки с Wall Street в том, что они пытаются сохранить и преумножить свои деньги — это всё ожидаемо. А вот что шифропанки могли бы несколько больше стоять на своих убеждениях и видеть такие разводки — было бы, конечно, неплохо.
(00:06:57) Сергей Тихомиров: То, что ты говоришь, очень перекликается с прошлым выпуском 206, где у нас был в гостях Влад Деген. Он рассказывал, насколько большую долю расходов обычного стартапа составляют compliance и legal, и что с точки зрения технологии, видимо, как раз эту дихотомию тоже можно подсветить: если человек хочет просто сделать стартап в крипте, по технологии более-менее понятно — все готовые компоненты уже есть, нужно их просто в нужном порядке совместить. Вопрос в том, как ты будешь compliance и сколько миллионов или десятков миллионов долларов заплатишь юристам, чтобы они сделали свои юридические штуки, учитывая, что большие игроки с другой стороны работают со своими юристами, чтобы тебе не разрешить с ними конкурировать.
(00:07:39) Кирилл Пименов: И это абсолютно понятная проблема, в целом результат того, что мы все как-то недостаточно идеалистичны, шифропанки. Мне кажется, этот шифропанкский идеализм должен был быстрее вырываться в реальный мир, и сейчас у нас проблема в том, что идёшь по Каннам, по Бангкоку, по криптоконференциям — всё красивое, большое, много проектов, миллионное финансирование. Люди объявляют, например — я очень не люблю говорить плохо про конкретные проекты, поэтому дальше будут аморфные указания на фонды и проекты — «у нас первый настоящий он-чейн-банк». О классно. В твоём он-чейн-банке у меня автомастерская, я хочу купить второй подъёмник и расшириться — как мне получить в твоём банке кредит? «Можно оставить NFT как залог». Понятно, вы страшно далеки от народа. Это странная ментальная проблема, но она приводит к тому, что надо где-то брать реальных пользователей. Где мы их берём? Там, где уже есть банки. Мы идём в ту же нишу и пытаемся сделать то же самое, просто чуть подешевле. Многие банки внутри вместо своих ужасных систем на COBOL радостно пилят Hyperledger Fabric до сих пор — я в открытой коррекции не встречал упоминаний с 2019 года, но внутренние системы. И всё становится быстрее, надёжнее, они радуются — это не совсем цифровой кэш без участия государства, который мы, наверное, хотели бы, чтобы остановить чёртову балканизацию планеты.
(00:09:23) Сергей Тихомиров: Да, слушай, давай тогда перетечём к более конкретным аспектам нашего разговора. Я бы хотел довольно подробно поговорить про хардверный кошелёк Kampela. Удивительно, что, изучая его, я узнал, что это финское слово и что русское «камбала» происходит от этого финского слова, означающего плоскую рыбину. Расскажи, пожалуйста, про историю, откуда вырос этот проект. Мне кажется, ты уже довольно давно занимался в каком-то смысле девайсами для подписывания блокчейновых транзакций. Как ты пришёл к современному видению?
(00:09:52) Кирилл Пименов: Да, во-первых, не просто плоскую рыбину, а плоскую рыбину с электронными чернилами на одной стороне, что ещё более похоже на тот кошелёк, который у меня в итоге получился. Собственно, моя предыстория: я был ответственным за всякого рода безопасность и пользовательские проекты в области безопасности в Parity, и один из важных проектов. В какой-то момент было смешно, что я как будто бы CISO, но у меня единственный client-facing продукт, который вообще у компании есть, — это Parity Signer. У нас была, и это продолжает работать, идея: если взять свой старый телефон, на котором уже есть secure enclave и в целом шифрование диска, то из него получится довольно пристойный офлайновый подписыватель транзакций.
(00:10:35) Кирилл Пименов: Офлайновый в том смысле, что ты его вообще навсегда загоняешь в самолётный режим, и дальше всё взаимодействие с внешним миром — это камера и экран смартфона. Экран смартфона прекрасный, он гораздо больше, чем на тот момент экраны, которые могли предложить Ledger и Trezor. На нём видно многие транзакции, потому что транзакция реального мира — это не «отправить 10 долларов кому-то один раз». Например, кто-то сидит в компании на 100 человек и отправляет payroll, у него 100 записей в одну транзакцию, желательно, и он их все отправляет. Чем больше экран, тем больше информации влезает и тем больше вероятность, что какую-то ошибку мы действительно заметим.
(00:11:15) Кирилл Пименов: Parity Signer жил-жил, сейчас он называется Polkadot Vault и получил прекрасную новую жизнь в руках классной продуктовой команды Nova Wallet. Он продолжает быть опенсорсным, кто-то потихоньку начинает пилить похожие решения, но в целом он в своём классе единственный, уникальный. Там придумали довольно много забавных штук, потому что как только начинаешь делать офлайновые кошельки, ты неизбежно сталкиваешься с фундаментальной проблемой аппаратных кошельков — можно прямо секцию так назвать. Она состоит в том, что у блокчейнов, если мы не берём совсем простой Bitcoin или что-то такое, есть какая-то семантика того, что ты с ними делаешь, и она зависит от того, в каком состоянии блокчейн сейчас находится. Самое простое: я пытаюсь перевести деньги, у меня таких денег нет, транзакция зафейлится, но офлайновый кошелёк об этом не знает. Более сложные вещи — вызов смарт-контрактов на EVM-сетях, где вообще непонятно, что ты вызываешь, если у тебя нет информации об ABI или возможности как-то просимулировать этот смарт-контракт в виртуализированном environment. Ты даже не знаешь, как называется тот метод, который ты вызываешь.
(00:12:27) Сергей Тихомиров: Follow-up вопрос: действительно, это одна из тем, которую я хотел позже осветить. Давай подробнее остановимся. Насколько я понимаю, в большой части случаев всё равно аппаратный кошелёк предполагает использование его с каким-то companion application, который находится онлайн. В чём проблема, если у меня есть онлайновый кошелёк, он подтянет информацию из блокчейна, мне её покажет, а аппаратный кошелёк будет только подписывать?
(00:12:52) Кирилл Пименов: Потому что онлайновый кошелёк не у тебя. Онлайновый кошелёк у атакующего, а то, что это атакующий на твоём компьютере, — техническая деталь, которая не очень важна в общей картине мира. Весь смысл аппаратного кошелька в том, что у нас есть какая-то доверенная платформа, которую гораздо сложнее взломать, особенно через интернет и без физического присутствия, чем твой настоящий компьютер. Если бы мы могли доверять тому, что выходит на экран твоего настоящего компьютера, аппаратный кошелёк вообще не нужен.
(00:13:15) Кирилл Пименов: И там много интересных философских и шифропанковских вопросов: может быть, мы можем увеличить аппаратный кошелёк до большой доверенной аппаратной платформы, которая занимает весь твой ноутбук, — это то, что Microsoft, например, делает. Microsoft делает свои trusted environment, требует от производителей ноутбуков для Windows 11, чтобы они там были, там есть Windows Hello, обязательно сканер отпечатка пальцев, это движение в ту сторону. К сожалению, это означает, что компьютер перестаёт быть твоим и начинает быть компьютером Microsoft, но зато не у мошенников — что лучше, непонятно.
(00:13:57) Кирилл Пименов: Поэтому ты не можешь полностью довериться тому, что видит твой онлайн-кошелёк. Его могут взломать десятью разными способами. Мы все помним недавнюю атаку на Multisig Gnosis: не то что у тебя на компьютере — через глобальный CDN, supply chain атаку и отравление, по-моему, node modules, на компьютере одного из разработчиков был установлен backdoor, который активировался у конкретного клиента при конкретной транзакции и что-то подменял в том, какую транзакцию действительно подписывает Gnosis, а на экране ты видел всё нормально. Это та модель атаки, которую мы вообще имеем в голове, когда говорим про аппаратные кошельки.
(00:14:38) Сергей Тихомиров: То есть правильно ли было переформулировать так: изначальный для меня, по крайней мере, pitch аппаратного кошелька заключается в том, что приватные ключи хранятся только на нём, они никуда не утекают, а утекает только подпись, которая и так публичная информация. Но подпись состоит из двух компонентов: то, что ты подписываешь, и приватные ключи, которыми ты подписываешь. Даже если мы обеспечим хранение приватных ключей супербезопасно и они никуда не утекут, второй компонент — собственно то, что ты подписываешь, — в этом главная загвоздка безопасности: обеспечить, чтобы действительно подписывалось то, что ты думаешь, что подписывается.
(00:15:10) Кирилл Пименов: Да, и это не чисто крипто-штука. Когда ты подписываешь договор с банком, тебя всегда просят читать мелкий шрифт, потому что там тоже есть backdoor'ы, которые пользуются тем, что у тебя в голове нет всего кодекса знаний о том, как устроена эта индустрия, они пытаются тебя где-то прожать. Это абсолютно понятная, обывательская история, просто она гораздо более наглядна и бинарна в случае кошелька, который ничего не знает о том, что там за чейн и куда ты переводишь. Самое простое техно-объяснение, которое я обычно использую: твой кошелёк не может про все токены знать, сколько у них знаков после запятой. Мы правильно делаем fintech на блокчейне: делаем его в int'ах и числах с фиксированной запятой, не используем float, мы молодцы, мы лучше нескольких больших немецких банков, про которые я слышал разные истории про то, какой у них внутри соус работает. Но ты не можешь это знать про все токены, и выходов у тебя два. Либо зашиваешь знания о каких-то дефолтных, самых частых токенах в прошивку — тогда прошивка обновляется каждый божий день, что само по себе проблема: что будет, если я не обновил; что будет, если кто-то поставил backdoor в обновление, а я привык каждый раз, когда пользуюсь кошельком, сначала обновлять прошивку — целый спектр вопросов. Второй способ — каким-то образом убедить блокчейн потом проверять не то, что ты показывал человеку на экране как транзакцию, а какие знания ты использовал, чтобы это человеку презентовать: иметь словарь, метаданные про транзакцию, которые блокчейн потом сможет проверить. Потому что блокчейну мы верим: если кто-то сможет заставить блокчейн принять неправильную транзакцию или плохо что-то посчитать, мы все обречены, это всё не имеет смысла, никакие деньги никуда не подходят.
(00:17:01) Сергей Тихомиров: Окей, я не верю, что понимаю второй путь. Есть блокчейн, на нём живут смарт-контракты, токены с разным количеством знаков после запятой и так далее. У меня есть аппаратный кошелёк, я хочу отправить транзакцию. Чтобы её корректно подписать, нужно знать, сколько именно у этого токена знаков после запятой. С первым способом, как мне кажется, я понял: зашиваем в прошивку информацию, что у этого токена столько-то знаков, в следующий раз обновится, подтянется другой токен, если он появится. А второй способ предполагает, что мне не совсем понятно, как блокчейн может знать или почему ему должно быть дело до того, что у меня происходит локально между моими устройствами, где я подписываю транзакцию.
(00:17:49) Кирилл Пименов: Давай это разберём побольше. Мы попадаем в мир людей, которые сделали прекрасные GitHub-репозитории «что происходит, когда я ввожу Google.com в браузер и нажимаю Enter», и там до электросхемы они вниз разбирают, как работают свечи на аппаратном уровне — прекрасная абсолютно нердовская тема.
(00:18:05) Кирилл Пименов: Останавливай меня, если я пойду слишком вглубь, но в целом идея такая. На горячем конце, на твоём ноутбуке, генерируется транзакция, которая по сути просто последовательность байтов. Мы с тобой уже решили, что эти байты без дополнительного внесения информации в целом не имеют однозначного смысла, который можно было бы проинтерпретировать, потому что они опираются на знания о том, что на цепочке прямо сейчас произошло. Когда они попадают на аппаратный кошелёк, тебе надо как-то это пользователю показать. Самое плохое, что ты можешь сделать, — показать эти байты и сказать: дальше танцуй, как хочешь, на этом мои полномочия всё.
(00:18:40) Кирилл Пименов: Неизбежно большинство разработчиков аппаратных кошельков говорят, что у нас есть не очень безопасный режим, мы не очень любим его пользователям давать, потому что им, кроме USDC переводить со счёта на счёт, ничего на самом деле не надо, поэтому мы это заблокируем. Если хотите, поставьте галочку, вы будете подписывать свои несчастные хэши.
(00:18:55) Сергей Тихомиров: Сейчас, подожди, этот небезопасный режим для профи-юзеров предполагает что именно? Показывание собственно хэша, показывание этих байтов?
(00:19:10) Кирилл Пименов: Да, показывание всех транзакций в байт-коде. А ты, видимо, у тебя такая большая транзакция в клеточку, ты туда эти байты выписываешь и сам как-то их парсишь. Я не знаю, что в голове у людей, которые считают, что это нормальная модель безопасности.
(00:19:21) Сергей Тихомиров: Меня просто удивило: я довольно нечастый пользователь аппаратных кошельков, мне нужно это делать, но редко, не каждый день. У меня была ментальная модель, что да, аппаратный кошелёк мне показывает набор байт, и это некоторый театр безопасности, потому что они делают вид, что я могу это проверить, а я глазами, конечно, не могу. Из того, что ты говоришь, я делаю вывод, что даже в нормальном дефолтном режиме пользователю эти байты не показываются. Ему показывают просто: ты переведёшь 100 USDC на такой-то адрес.
(00:19:51) Кирилл Пименов: А если ты переводишь не USDC, а свежий токен, которого в прошивке нет, то ему говорят: это транзакция, которую я не могу тебе показать, подумай ещё 10 раз и включи опцию, если тебе реально надо, но скорее всего тебя обманывают. Может, это даже правильно, может в mass-market ты должен так жить, но кажется, можно придумать лучше. Мы собрались сложные проблемы решать в теории криптографии информации, а тут все «у меня лапки».
(00:20:13) Кирилл Пименов: Но ведь можно — почему я не могу распарсить произвольную транзакцию, разобрать её на байтики и показать их в человекопонятном виде? Потому что у меня нет дополнительных допущений про то, что эти байтики особо означают: байтик с четвёртого по восьмой — это длина строки, которую я подписываю дальше, или десятый байтик — количество десятичных дробных частей токена, которые я перевожу, а чтобы перевести это в общий токен, мне надо ещё умножить на десять в десятой, потому что у него десять знаков после запятой, что-нибудь такое. Все эти допущения на горячем конце в целом есть. Как раз хорошие кошельки — MetaMask, Rabby, прекрасные штуки — очень стараются по максимуму доставать эти допущения из того, что ты видишь. Знание о том, как байт-код соответствует человекопонятным вещам, оно есть. Проблема в том, что даже если ты его передашь на аппаратный кошелёк, ты никак не сможешь убедиться, что тебе рассказали правду и ты переводишь действительно один доллар, а не сто, потому что запятая не в том месте.
(00:21:21) Сергей Тихомиров: Ага, то есть получается, что мы используем слово «кошелёк» в нескольких разных смыслах, и это немного осложняет разговор. Я сейчас попробую выражаться чётче. Кошелёк, который живёт на онлайн-устройстве, в принципе может всё подтянуть, всё проинтерпретировать и сказать: ты собираешься писать вот такой байт-код, и учитывая всё, что я знаю про чейн и про всё на свете, вот его интерпретация. В принципе я мог бы дальше сравнить то, что мне показывает аппаратный кошелёк, и то, что мне показывает онлайн-кошелёк. Но если онлайн-кошелёк взломан, он мне покажет фейковый хэш и здесь, и там, и то, что эти штуки будут совпадать, тоже ничего не показатель.
(00:21:55) Кирилл Пименов: Да, довольно правильно. Давайте действительно терминологию введём: люди часто теряются, когда я называю эту штуку сайнером — она сайнер, а железка не кошелёк, потому что она не знает, сколько у тебя в нём денег. Довольно дурацкий кошелёк был бы физически, если бы я мог положить деньги, достать деньги, но не знал, сколько там внутри. Значит, это сайнер. Кошелёк — приложение, с которым ты взаимодействуешь, чтобы собрать транзакцию, куда-то с кем-то что-то перевести, вложить, подписать. Аккаунт или счёт — это то, что у тебя на блокчейне, где записано, сколько у тебя сейчас токенов в тех или иных.
(00:22:28) Сергей Тихомиров: Учитывая эту фундаментальную проблему или задачу, как к ней подходят разные существующие производители аппаратных кошельков? Как здесь смотрится Kampela в этом пейзаже? Почему нужен ещё один аппарат, ещё один сайнер? И как вы решаете эту проблему по-другому, если решаете по-другому?
(00:22:52) Кирилл Пименов: Мы придумали, как решать её по-другому, поэтому Kampela и нужна — смысл понятен. Ledger делает ровно то, о чём мы говорили: он пытается максимально хорошо отражать реальность самого частого пользователя. Для этого им нужны Ledger Live и телеметрия — они хотят знать, какие токены у тебя есть, чтобы в следующем релизе прошивки зашить информацию именно об этих токенах и правильно показывать, сколько знаков после запятой.
(00:23:17) Кирилл Пименов: Я безумно упрощаю — понятно, что там надо парсить не только знаки после запятой. Чем сложнее контракты, тем сложнее их впихнуть, и тем сложнее впихнуть их в Ledger Nano S. Одна из причин, почему они сейчас пытаются свести его с рынка: кроме того что очень хочется есть, отличный бизнес-план — забриковать старые девайсы, которых половина рынка, и продать вместо них новые.
(00:23:35) Кирилл Пименов: Кроме этого, прошивки, особенно прошивки DeFi-богатых сетей, очень раздуваются — туда постоянно надо зашивать большое количество знаний про все мемкоины, которые вышли за последнюю неделю. И это никому невозможно впихнуть в приложение: какие там у них лимиты, я не помню, на базовых моделях что-то вроде 512 килобайт.
(00:24:05) Кирилл Пименов: Можно в целом делать лицо попроще. Можно вообще не защищаться от атаки со сложными подменами, а просто сделать так, что никто не может подписать все транзакции на свете от твоего имени — можно подписать только одну. Это проект Keycard, он прекрасен в своей простоте: готовые смарт-карты, карточки с чипом, просто прикладываешь к NFC сзади телефона — ни экрана, ничего, приложил, подписал. Это лучше, чем ничего, но это далеко не тот уровень безопасности, который в целом ожидается от современного лучшего в классе сайнера.
(00:24:41) Сергей Тихомиров: То есть в этой модели мы всё равно доверяем телефону, что он правильно покажет на экране, что мы подписываем, а сайнер просто подписывает всё, что ему телефон передаст.
(00:24:51) Кирилл Пименов: Да, и в этой модели мы защищаем следующее: если тебя не заставить активно хоть что-то подписать, ты карточку не приложишь, и атакующий в холодную не сможет просто убежать с твоими деньгами. Keycard молодцы — защищаются от самой простой атаки: прислать тебе вирус через MMS или по ссылке, которую ты кликнешь, стырить приватный ключ и после этого всегда и навечно иметь полный доступ к твоим деньгам без твоего взаимодействия.
(00:25:17) Кирилл Пименов: Заменить эту угрозу на то, что вирус на телефон установят, спровоцируют тебя с него отправить транзакцию, ты приложишь карточку — и тогда мы один раз сможем подписать от твоего имени что-то. И нам лучше бы проследить, что это что-то действительно переводит нам все твои деньги все и навсегда.
(00:25:36) Кирилл Пименов: Это улучшение ситуации, стоит нисколько, производится миллионами, взаимодействия там все понятные. Прекрасный проект — очень много разных способов решить одну и ту же security-задачу, потому что универсального решения нет.
(00:25:51) Кирилл Пименов: Но мы решили, что нам этого мало, и сначала для Polkadot придумали концепцию метаданных, метаинформации, которую блокчейн должен о себе сам знать. У блокчейна есть какое-то представление о том, как парсить собственные транзакции. Ему на самом деле не надо знать всю эту metadata и не надо ей оперировать. Ему надо знать Merkle root — хеш корня дерева Merkle, которое описывает весь этот словарь.
(00:26:15) Кирилл Пименов: Словарь может быть большой, там может быть мегабайт размером, но на девайсе тебе от него нужны иногда маленькие листочки. Ты будешь эти листочки получать, а в получившуюся цифровую подпись просто включишь: я подписал это, смотря на расшифровки с хешом Merkle root вот таким-то.
(00:26:35) Сергей Тихомиров: Сейчас — правильно ли я понимаю? Я сейчас изложу своё видение, ты меня поправь, если неправильно понял. Эта фундаментальная проблема, с которой мы начали — что невозможно удостовериться, что я подписываю то, что на самом деле имею в виду, — в каком-то смысле сводится к тому, что при компиляции в bytecode, по крайней мере в терминах EVM, теряется часть семантики: теряются имена переменных, структура какая-то сохраняется, но она недостаточна.
(00:27:04) Кирилл Пименов: Это вообще состояние сети, и я про десятичные знаки говорю именно поэтому: десятичные знаки не в bytecode, они просто лежат во вторичной ячейке стейта блокчейна — эта цифра.
(00:27:17) Сергей Тихомиров: Окей, сейчас, я тогда просто…
(00:27:18) Кирилл Пименов: Здесь, по-моему, number of decimals как вызов, если я не путаю.
(00:27:22) Сергей Тихомиров: Окей, я, наверное, тогда в твоём объяснении не совсем понял, что значит «блокчейн должен знать». Ethereum-блокчейн тоже знает, сколько у него знаков после запятой в каждом токене.
(00:27:34) Кирилл Пименов: Да, но его тяжело заставить проверять. Сложность в том, что тебе надо отправить транзакцию, которая кроме самой транзакции будет содержать набор ассертов, набор допущений: мы сейчас переводим USDC вот по такому адресу, здесь должно стать столько-то, здесь столько-то, десятичных знаков при этом столько-то, никаких других сайд-эффектов не должно произойти и ничего ещё.
(00:27:56) Сергей Тихомиров: А чем это отличается от простой валидации корректности транзакции в обычном сценарии?
(00:28:01) Кирилл Пименов: Ничем, но такая сложная транзакция требует ещё смарт-контракта. Да, ты можешь написать все эти ассерты, но это перестанет быть обычным трансфером — станет какой-то сложной развесистой структурой, которую ещё хрен пойми, как самому описать блокчейну. Но вообще мы можем так делать, конечно.
(00:28:14) Сергей Тихомиров: Подожди, давай так. Может, тут есть какая-то Polkadot-специфика, которую я не понимаю, но я буду интерпретировать это в терминах Ethereum, а ты скажи, если что-то фундаментально не так. Есть Ethereum, я могу на него задеплоить ERC-20 контракт, и там будет какое-то число decimals, возможная внутренняя логика, зашитая в этот стандарт. Дальше я хочу отправить тебе какое-то количество токенов, подписав их сайнером. Сайнер не знает, сколько у меня знаков после запятой, поэтому не может показать в человекочитаемом виде, что я собираюсь подписать.
(00:28:51) Сергей Тихомиров: Правильно ли я понимаю, что так или иначе на хардверный сайнер приходит какой-то байт-код? Сайнер его подписывает и отправляет обратно, и транзакция уходит в блокчейн. Но с той схемой, которую ты описываешь, транзакция не будет признана корректной с точки зрения блокчейна, если помимо своей семантики она буквально ещё не будет соответствовать дополнительным условиям, которые прописаны, — я честно говоря до сих пор не понял, где именно.
(00:29:23) Кирилл Пименов: В этом есть сложность. Это абстрактно нерешённая задача, её можно решать только тактически. Да, ты всё абсолютно правильно понял. Кроме того, в самой транзакции подпись должна включать дополнительную информацию о том, что именно я делал, чтобы показать это пользователю как нормальную человеческую транзакцию.
(00:29:41) Кирилл Пименов: Это можно называть метаданными, можно словарём, можно UX Assumptions — неважно, как мы это называем. Надо сделать так, чтобы блокчейн на своей стороне мог удостовериться, что то, что кошелёк использовал, полностью соответствовало его представлениям. Если не совпадёт, подпись не принимается, транзакция невалидна. В этом плане горячий коннект не может надурить пользователя: послать ему неправильную информацию о состоянии блокчейна, о количестве нулей, о членах multisig или о чём-то ещё и подвести его подписать не ту транзакцию, которую он видит на экране в семантически разобранном виде.
(00:30:21) Сергей Тихомиров: Я сейчас понял, чего я не понимаю. Если мы в модели безопасности предполагаем, что онлайн-кошелёк может быть скомпрометирован, он просто подменит адрес, куда я отправляю монеты. Мне сложно понять с точки зрения блокчейна, чем отличается транзакция: я тебе послал десять своих кастомных токенов или USDT, или USDC, или я послал их злоумышленнику, который захватил мой компьютер и подменил твой адрес своим. С точки зрения блокчейна это просто два адреса. Как блокчейн может что-нибудь сказать в этом случае?
(00:30:56) Кирилл Пименов: Чего мы не можем сделать — тут только небольшие UX-улучшения. Они состоят в том, что пользователь в общем знает про адреса. В отличие от остального, например decimals в стандарте ERC-20: то, что он переводит что-то на какой-то адрес, этот адрес примерно похож на длинный IBAN, по которому он обычно переводит в банке, — в общем он это понимает.
(00:31:19) Кирилл Пименов: И в этом плане можно как-то помочь, но никто никогда в жизни — я видел транзакции на сто миллионов долларов одним куском — не встречал людей, которые без подсказки через плечо проверяли бы все буквы в адресе. Но к счастью мы придумали разные способы визуально хэшировать эти адреса и рисовать картинки, которые адресам соответствуют.
(00:31:42) Кирилл Пименов: Если в экосистеме принят какой-нибудь такой стандарт — будь то рожи каких-то шифропанков, которые из твоего хэша генерируются, или в Polkadot приняты doticons, такие круглые картинки с разной радиальной симметрией и разными цветами, — на мой взгляд, недостаточно дальтоник-friendly, но со стандартом уже ничего не сделаешь.
(00:32:04) Кирилл Пименов: Тогда мы можем убедиться, что хотя бы базовую проверку того, что адрес не подменился, мы сделали. А дальше, как обычно, люди смотрят первые четыре символа, последние четыре символа, в целом что-то такое «по вайбам» проверили — и большей части народу этого достаточно.
(00:32:20) Кирилл Пименов: В этом плане адреса можно показывать, их надо дальше дорабатывать с точки зрения user-friendliness — это большая экосистемная задача. Но если ты в целом не переусложнил UX всего процесса, и человек не вынужден снова прокликивать байт-коды на Ledger по двадцати экранам, — даже в multisig три из пяти кто-нибудь проверил: на раз так обычно садятся, каждый думает, что остальные проверили.
(00:32:52) Кирилл Пименов: Адрес — меньшая из проблем, потому что хотя бы есть взаимное ожидание, что мы на него посмотрим, мы понимаем, что он участвует в разговоре, и если его подменить, будет плохо. А вот показывать человеку: «вы знаете, у USDC восемь знаков после запятой» — ответ какой? Невозможно заставить человека знать это про все токены, с которыми он взаимодействует. Особенно невозможно, когда он на DEX меняет одно на другое.
(00:33:10) Сергей Тихомиров: OK, fair enough. Проблема, я думаю, для меня по крайней мере стала понятнее, но пока не совсем понятно решение. Как блокчейн может отличить транзакции? OK, допустим, похожий сценарий атаки: атакующий захватил мой компьютер, и тот факт, что я дотошный человек и сверил каждый символ адреса, или что они представлены картинками, которые легче сравнивать глазами, — это предотвращает атаку с тупой подменой адреса получателя. А если подменено что-то ещё?
(00:33:38) Кирилл Пименов: Класс, это очень правильный вопрос, и это сложный вопрос, к которому мы уже полчаса разговора подходили. Не потому что я плохо объясняю или ты плохо спрашиваешь. Просто это натурально не самая очевидная тема во всей этой безопасности и ещё нерешённая проблема, поэтому люди из аппаратных кошельков обычно не очень любят про неё говорить. Но да, вопрос в том, как убедиться, что все эти дополнительные допущения корректны.
(00:34:07) Кирилл Пименов: Можно ничего не делать — Keycard так делает, и в целом можно просто поверить. Можно иметь хардкод: это то, что делает Ledger, отчасти Trezor. У Trezor поменьше инженерная команда, поэтому видно, что они больше всего не поддерживают и предлагают тебе самому оперировать байт-кодами. Но в целом это такое индустриальное стандартное решение.
(00:34:30) Кирилл Пименов: Но можно в некоторых блокчейнах, специально написав дополнительную обвязку и как бы «ужа с ежом подружив», научить подпись над транзакцией нести дополнительную информацию, кроме самой транзакции. Если говорить инженерно, это все дополнительные куски информации, которые мне были нужны, чтобы байт-код превратить в визуал на экране. Там может быть, что адрес такой-то, это токен с тикером USDC, что у токена столько-то знаков после запятой, и ещё несколько таких вещей. Тогда вместо байт-кода ты видишь: я перевожу 10 USDC со своего адреса на этот адрес. Мы поговорили, что адрес ты сравниваешь, а мы пытаемся помочь и рисуем их графикой, а не только буквами и цифрами.
(00:35:19) Кирилл Пименов: А всё остальное мы как-нибудь запихиваем в подпись. И давай теперь расскажем, как мы это решали на Polkadot. Для этого надо чуть-чуть рассказать про Polkadot, потому что там это в целом уже решено, причём во всей экосистеме. Я очень доволен тем, что получилось.
(00:35:35) Кирилл Пименов: А потом я чуть-чуть коснусь того, что мы думаем, как это можно сделать на Ethereum. Но тут момент такой: почему Kampela до сих пор не продаётся из каждого утюга? Потому что мы не на 100% уверены, что наши решения корректны. Мы плотно работаем с Ethereum Foundation, мы сейчас, скорее всего, получим грант на то, чтобы эту технологию полностью провалидировать и опубликовать. Я надеюсь, другие кошельки тоже будут вместе с нами пользоваться именно нашим решением.
(00:36:00) Кирилл Пименов: Но я по суеверным, в первую очередь, причинам не хотел бы публиковать прямо сейчас наши идеи до того, как мы убедимся, что они всегда в 100% случаев работают. Поэтому я буду чуть-чуть обходить стороной какие-то конкретные способы устроить именно это на EVM-сетях.
(00:36:23) Кирилл Пименов: Но начнём с Polkadot: там есть RFC, который уже имплементирован. Polkadot, все Substrate runtime ему обучены, и это позволило сделать то, что на Ledger сейчас называется Ledger Unified App. То есть кроме нашего хардверного кошелька Ledger Unified App для Polkadot и Substrate-сетей тоже знает про этот принцип подписания дополнительной метаданных. Поэтому можно сделать одно Ledger Unified App для всех приложений на Substrate, и оно при этом будет тебе магическим образом на каждом блокчейне его специфические транзакции правильно парсить.
(00:36:58) Кирилл Пименов: И это всё опирается на довольно странную особенность Polkadot: на большом количестве Polkadot-чейнов нет вообще смарт-контрактов, и они не очень нужны. Потому что если мы посмотрим, как даже на EVM какие смарт-контракты используются, а какие нет, у нас будет гигантское бимодальное распределение: здесь ERC-токены, ERC-20, NFT и что-то ещё, и всё остальное мелкое.
(00:37:25) Кирилл Пименов: Polkadot, вообще Substrate как фреймворк, предполагает, что эти типовые вещи ты будешь прямо хардкодить в runtime, будешь иметь к ним специальные системные вызовы. У тебя не будет байт-кода, который надо интерпретировать на каждый такой вызов. Мы прямо возьмём и в виде WebAssembly blob выложим это, и все наши узлы сети будут знать, что транзакция номер 127 — это asset transfer, и она переводит asset с таким-то ID с такого места на такое.
(00:37:50) Сергей Тихомиров: Вопрос опять-таки в эфирной терминологии: правильно ли я понимаю, что это похоже на precompile, только, возможно, на более высоком уровне абстракции? То есть мы не делаем так, что каждый нод знает, что такой-то байт-код — это ZKVerify и что-нибудь такое, а мы говорим, что такой-то transaction ID — это token transfer?
(00:38:12) Кирилл Пименов: Да, и это похоже на precompile с заметной оговоркой. Благодаря тому, что у нас есть концепция runtime, извиняюсь, governance — всё это, что Polkadot сделал и другие Substrate-цепи подхватили — это в целом довольно живая, бурлящая среда, в которую довольно легко с ведома всех стейкхолдеров добавлять фичи. Она занимает место где-то посреди между Ethereum precompile и Ethereum смарт-контрактами, потому что у неё есть governance, и она без остановки и перезапуска клиента на всех клиентах начинает быть новой после часа X. Знание про все эти precompile составляет метаданные для конкретной цепочки.
(00:38:57) Кирилл Пименов: И эти метаданные мы в целом можем, пока мы делаем runtime — у неё исходный код, мы его компилируем — добавить шаг на компиляции, который говорит: а также скомпилируй нам, пожалуйста, весь словарь метаданных, что transaction, например, такая-то, делает то-то, и у неё вот такие-то параметры, которые являются вот такими-то типами данных. Собираем это всё, упорядочиваем в нужном порядке, делаем дерево Merkle и кладём этот хэш как раз в фичу runtime, которая проверяет подписи.
(00:39:25) Сергей Тихомиров: То есть правильно ли было бы, возможно, как-то переформулировать и убедиться, что я, по крайней мере, правильно понял: дерево Merkle, которое собирает в себе информацию о том, грубо говоря, у какого токена сколько знаков после запятой и похожего рода вещи, собирается в один root, и этот root становится частью логики нода, который оперирует самим блокчейном. И этот нод знает, что, окей, если мы сейчас находимся в интервале block height с миллиона до двух миллионов, у нас такая-то логика плюс она валидна при условии таких-то метаданных, а на блоке два миллиона у нас следующее governance-голосование, у нас будет обновление этих метаданных, и там, возможно, что-то меняется или добавится. Но что пока из этой картины мне не совсем понятно — как здесь хардверный сайнер вписывается в эту картину?
(00:40:15) Кирилл Пименов: Я давай сначала чуть-чуть ещё пофлексую технологией, потому что самое забавное, что этот хэш будет у всех транзакций одинаковый. Все транзакции там в одном блоке будут иметь этот хэш одинаковый, а он какой-то длинный, типа 16 байт, может быть, 30 байт.
(00:40:30) Сергей Тихомиров: В смысле Merkle root всех метаданных.
(00:40:36) Кирилл Пименов: Да, Merkle root метаданных. А давайте мы не будем его в транзакцию на блокчейн класть. Пусть в транзакции будет какое-то количество полей в записи, к которой подпись прилагается, которые имплицитны: мы просто знаем, что они есть. Дальше узел, когда транзакцию валидируют, берёт эти имплицитные записи, надувает их текущим знанием и сверяет, сошлась ли подпись. Если мы попытаемся положить транзакцию, закоммиченную на неправильный хэш, у нас просто не сойдётся подпись.
(00:41:07) Сергей Тихомиров: Это, в свою очередь, немножко напоминает чекпойнты в Bitcoin или вообще логику в духе того, что, в принципе, мы можем какие-то куски валидации заменить на захардкоженные значения прямо в коде клиента. Один из аспектов валидации транзакции будет проверить, что эти захардкоженные значения соответствуют тому, что ожидается. Это, возможно, немного притянутый за уши пример, но понятно.
(00:41:31) Кирилл Пименов: Нет, это прекрасный пример, потому что он сразу открывает очевидный простор для обсуждения того, как мы решаем, какие эти захардкоженные значения хороши и какой у них жизненный цикл, кто решает, что их пора обновить, как это доносится до клиентов. Как раз вся эта восхитительная штука про governance, с которой мы только-только потихонечку начинаем быть уверенными, что наше решение хотя бы имеет смысл сейчас.
(00:41:53) Кирилл Пименов: Ну что же делать? Блокчейн — киберсоциальная система. Кибер менять быстро, социальная — медленно. И нашли ли мы оптимальное решение, которое на голову лучше всех остальных? Нет, но хотя бы мы понимаем, где у нас trade-off'ы. А дальше оказывается, что всё равно надо больше, прости, Господи, гуманитарных технологов, потому что все понимают в этом governance про то, как приходить к результату выборов, но никто из технологов не понимает, откуда вообще берутся вопросы, которые стоят и не стоят голосования. И самая большая уязвимость большинства систем governance, которые я видел, — это курирование повестки следующих выборов и т. д.
(00:42:33) Кирилл Пименов: Там много очень интересных полусоциальных дырок, начиная со спама инициативами, имеющими какой-то смысл, но не очень полезными, и заканчивая тем, что многие акторы не имеют достаточно голоса и не могут свою валидную проблему поставить на голосование для поиска решения. Это очень фундаментальный гуманитарный вопрос, и поэтому программисты обычно делают круглые глаза. Я пытался и буду продолжать пытаться со всеми, кто имеет отношение к дизайну governance, разговаривать именно про это: как вы убеждаетесь, что вопросы, которые стоят, они… кто у вас контролирует повестку? На любом круглом столе контролирующий повестку секретарь вообще сам не важный, а даже не президент каких-нибудь корпораций, которые собрались обсудить свой картельный сговор.
(00:43:24) Сергей Тихомиров: Слушай, я подумал: не зря, наверное, главная должность в коммунизме называлась генеральный секретарь — так и называется в некоторых странах.
(00:43:32) Сергей Тихомиров: Хорошо, давай вернёмся к сайнерам. У нас есть метаданные на блокчейне, и ноды валидируют транзакции с учётом этих метаданных, про которые есть какой-то неявный консенсус из governance. Допустим, governance работает идеально. А как аппаратный сайнер об этом узнаёт?
(00:43:46) Кирилл Пименов: Когда мы передаём с горячего кошелька на сайнер транзакцию, я говорю про метаданные с таким root hash. Я буду передавать тебе байты, и к каждому сегменту байтов предложу Merkle-ветку от нашего hash, про который мы договорились. Ты будешь использовать эту Merkle-ветку — знание того куска информации, который лежит в ячейке, — чтобы эти байты распарсить. Я буду так это стримить: тебе не надо ничего хранить, ты складываешь байты транзакции в одну ячейку памяти, а информацию выводишь на экран — этот кусочек.
(00:44:32) Кирилл Пименов: Merkle-ветку метаданных можешь забыть, я пришлю снова, когда в следующий раз понадобится. Предположим, batch-транзакция: десять раз переводим один и тот же стейблкоин — я десять раз пришлю его десятичную позицию, мне это не в тягость, а тебе не надо хранить все метаданные и из них что-то доставать, потому что ты несчастный маленький аппаратный кошелёк, у тебя килобайты оперативки, и лучше всё стримить, а не сохранять. Кошелёк это использовал, показал в интерфейсе. После этого, кроме пикселей на экране, у него есть Merkle-root, которому он доверяет: наши пиксели соответствуют интенциям в транзакции. У него есть все байты транзакции, потому что он их аккуратно складывал, и он может одно с другим сконкатенировать, подписать и послать обратно. Получается подпись, закоммиченная на конкретное состояние метаданных.
(00:45:26) Сергей Тихомиров: То есть это предотвращает ранее описанную атаку в том смысле, что злоумышленник не может подменить метаданные: если их подменить, это не срастётся в блокчейне. У блокчейна метаданные есть, и их подменить нельзя. Соответственно, атаки вроде подделки десятичных знаков становятся невозможными по этой причине.
(00:45:51) Кирилл Пименов: Именно так. Они становятся невозможными, но злоумышленник всё ещё может подменить данные так, что получится невалидная транзакция. Он по-прежнему может послать невалидную транзакцию на кошелёк и иначе задосить нашего пользователя. От этого аппаратный кошелёк защитить не может. В крайнем случае для DoS можно отформатировать компьютер, с которым пользователь привык работать. Ключи всё равно на аппаратном кошельке, он может подключить его куда-то ещё и всё сделать. Это максимум неприятностей, которые атакующий в такой модели может причинить.
(00:46:25) Кирилл Пименов: Всё ломается, когда начинается более свободное изменение смарт-контрактов, когда не нужен governance и нет централизованных метаданных. Это серьёзная реальность, в которой мы живём в EVM. С одной стороны, у нас нет обновления runtime, поэтому мы не можем закоммитить туда сегодняшнюю конкретную метадату. У нас нет даже механизма, чтобы подписи проверялись опционально новым способом с метаданными, включёнными куда-то. Абсолютно невозможно провести форк, который бы это требовал — это out of scope любого проекта, который над этим бьётся. Значит, надо придумать что-то другое: способ, чтобы транзакция, которую мы в итоге подписали, включала ещё набор этих assert-ов.
(00:47:12) Кирилл Пименов: Это похоже на две вещи: на account abstraction и на Flashbots. Где-то здесь мы ищем изящные решения, которые будут работать на всех EVM. Почему похоже на account abstraction? Потому что account abstraction как раз нужен, чтобы твоя транзакция триггерила внутреннюю EVM-машинерию, что-то вычисляла, а не просто переводила деньги со счёта A на счёт B. При этом эта машинерия может быть неявно включена в транзакцию. Это единственный способ делать с транзакциями на Ethereum что-то неявное: они очень ценят обратную совместимость, поэтому транзакция, которая делает transfer, делает transfer. Но если исходящий адрес — account abstraction адрес, мы делаем ещё что-то. К сожалению или к счастью, в account abstraction нельзя положить абсолютно любое вычисление: там жёсткие ограничения на то, к каким ячейкам знания о блокчейне account abstraction contract может обращаться. Вторая неловкость: account abstraction сначала надо задеплоить. Чтобы начать работать с кошельком, его надо инициализировать. Нельзя просто взять адрес, на него что-то получить и отправить.
(00:48:37) Кирилл Пименов: Второй подход, который используют для защиты от MEV и сэндвич-атак, — Flashbots-контракты: они позволяют в дополнительную транзакцию заложить набор допущений и проверок и закоммитить свою транзакцию на то, что предыдущая войдёт в тот же блок и вернёт true. Я безбожно упрощаю, и Flashbots — это не только он-чейн кусок, но и большая оф-чейн инфраструктура. Но этот подход тоже похож на то, что нам нужно: мы хотели бы, чтобы наша транзакция выглядела как обычная — transfer, вызов контракта и так далее, — но имела дополнительное свойство: она опирается на допущения, и если они неверны, она не выполнится.
(00:49:25) Кирилл Пименов: Это открытый вопрос и одна из последних фундаментальных вещей, которые мешают сделать Kampela полноценно EVM-compatible и начать массово продавать. Массово продавать девайс, который не поддерживает самые массовые сети для перевода ценностей из кармана в карман, — глупость, мы даже не собираемся начинать. Мы продали несколько сотен девкитов, они существуют, у нас есть линии, которые их производят, но это девкиты: с ними можно играть, перепрошивать, люди делают разные странные штуки. Я люблю всем тетрис на ней показывать.
(00:49:55) Сергей Тихомиров: Давай поговорим про другой аспект архитектуры сайнера, который, мне кажется, стоит осветить. У меня, возможно, устаревшие представления, но в моей картине мира есть вечное противостояние: используют ли в архитектуре сайнеров secure element и как его правильно применять. Настолько я понял, готовясь к выпуску, — поправь, если неправ — что Trezor, Ledger и, возможно, другие производители более или менее унифицируют подход, и топовые модели используют secure element так или иначе.
(00:50:36) Кирилл Пименов: Тут есть забавная тонкость: когда ставишь secure element, выбор криптопримитивов, в которых можно шевелить ключами, становится очень ограниченным. Самый очевидный пример — IOTA со своим троичным шифрованием. Нет ни одного чипа на планете, вопреки желаниям фаундеров, который это сейчас имплементирует или когда-нибудь имплементирует. Если говоришь, что это самый универсальный чип, который поддерживает все блокчейны какие угодно, неизбежно получаешь, что ключами можно шевелить только вне защищённого периметра. Их неизбежно надо вытаскивать в общую память перепрошиваемого приложения под конкретный блокчейн, потому что там может быть любой алгоритм, хотя бы просто подписывание. Уже не говорю про парсинг, хеширование и всё такое.
(00:51:32) Сергей Тихомиров: Давай остановимся здесь подробнее. Подойдём со стороны Kampela. Расскажи, пожалуйста, как у вас устроено: есть ли secure element и как вы обходите его ограничения, если они мешают, как выстраивается взаимодействие между secure element и обычным процессором без защищённого криптографического enclave.
(00:52:00) Кирилл Пименов: Мы решили снобски, что блокчейны, которым нужно то, чего наш enclave не умеет, мы, скорее всего, никогда не сможем поддержать и не поддерживаем. Это не бесплатный trade-off, я очень понимаю проекты, которые делали иначе, но в текущем продуктовом виде Kampela мы хотим безкомпромиссную безопасность. Да: у нас хороший чип, на самом деле два чипа под одной крышечкой — общий чип и secure element, вставленный в него. У STM и у ESP в линейке всегда есть такие чипы. У нас большой инженерный документ про то, лучше ли всё под одной крышкой или два чипа и какие плюсы и минусы. Это может быть пересмотрено, с точки зрения логики разница не очень большая.
(00:52:58) Кирилл Пименов: Secure element у нас умеет вот это, вот это, вот это; научить его можно только алгоритмам вроде secp256k1 и другим понятным общеиспользуемым. Если у вас что-то особенное — извините, вы не получите от этого железа те же гарантии безопасности. Нам кажется гораздо важнее эти гарантии соблюдать, тем более что мы опенсорсные, и соблюдение или несоблюдение легко проверить по коду.
(00:53:30) Кирилл Пименов: Поэтому нам важно, чтобы код и маркетинговые пресс-релизы совпадали буква в букву. Ещё одна причина выбирать опенсорс для таких кошельков: я ощущаю давление на себе — хотелось бы приукрасить, но реальность не позволяет. Мы делаем только те примитивы, которые у нас есть, и наши ключи secure element действительно никогда не покидают.
(00:54:02) Кирилл Пименов: Дальше вопрос: как мы очерчиваем границы secure element и используем ли дополнительно у ARM trust-зоны — возможность разместить кусок основной памяти тоже как secure element-память, которую аппарат шифрует.
(00:54:24) Сергей Тихомиров: Уточняющий вопрос. Правильно ли я понимаю, что secure element всё-таки предполагает некоторое доверие к производителю чипа? И, видимо, из того, что ты говоришь, есть какой-то консенсус, что эти trade-off стоит брать и что преимущество того стоит? Или я чего-то не понимаю?
(00:54:45) Кирилл Пименов: Да, это вопрос доверия к любой микроэлектронике. Мало что можно сделать, чтобы полностью убрать риск, что производитель чипов где-то сделал не secure element. Моделей угроз здесь две. Одна — производитель просто не знает, что делает, у них лапки, они попытались сделать что-то secure, но не получилось.
(00:55:10) Кирилл Пименов: Intel SGX — настолько успешный проект, что с какой-то ревизии процессоров они перестали добавлять SGX в клиентские девайсы. Для серверной совместимости они ещё кладут его в серверные версии, а в потребительских десктопах SGX больше нет, потому что не получилось. В целом мы наблюдаем, что Intel немного идёт к закату, и хорошо, что появилось несколько альтернатив. При этом чем проще процессор и чем проще его криптографический security co-processor, тем лучше. Чем больше расстояние между людьми, которые дизайнят архитектуру, и людьми, которые реально делают чипы, тем лучше. В этом смысле ARM, наверное, лучше, чем Intel или AMD, потому что ARM дизайнит, а имплементируют уже другие.
(00:56:02) Сергей Тихомиров: Подожди, а почему лучше, когда разные люди дизайнят и имплементируют?
(00:56:07) Кирилл Пименов: Потому что люди, которые имплементируют, могут заметить, что те напроектировали херню. Квартальная премия человека, который имплементирует, не зависит от того, хорошо ли он задизайнил.
(00:56:21) Сергей Тихомиров: Просто я предполагаю, что на это можно посмотреть и с другой стороны. Если, как написано на iPhone — у меня, кажется, никогда не было iPhone — «Designed in California, made in China»: ты дизайнишь в Калифорнии, а потом отправляешь на производство в Китай, то черт его знает, что там на китайском заводе по приказу компартии произойдёт. Можно и так поставить вопрос.
(00:56:40) Кирилл Пименов: Это безумно интересный вопрос. Я, кстати, подарил одну из Kampela знакомому — чуваку по имени Банни Хуан. Он сделал телефон Precursor. Сейчас у него проект инфракрасной интерферометрической спектроскопии, что ли. Как это описать? Он светит инфракрасной лампой на чипы и по интерференционной картине пытается понять, что там внутри, и совпадает ли этот чип с ожидаемым — неинвазивно.
(00:57:11) Кирилл Пименов: Потому что основная проблема в том, что чип залит компаундом, и дальше его надо сбрить, чтобы посмотреть даже под самым лучшим из возможных электронных микроскопов на то, что происходит под этой крышечкой. Чтобы понять, был ли у твоего аппаратного signer'а backdoor, его надо разрушить. Это не очень хороший подход.
(00:57:30) Кирилл Пименов: Поэтому есть некоторый набор подходов. Давайте я вспомню, как проект называется, и мы добавим его куда-нибудь под выпуском. Безумно интересная штука. В том числе он оптимизирован под do-it-yourself: в целом можно купить компонентов где-то за тысячу евро и самому у себя эти чипы валидировать.
(00:57:56) Сергей Тихомиров: Окей, возвращаясь к Kampela, мне было бы ещё интересно понять в отношении secure element и того, как он используется в вашей архитектуре. Правильно ли я понимаю, что по крайней мере в каких-то кошельках, возможно в устаревших дизайнах, проблема могла быть ещё и в том, что несмотря на то что подписи действительно генерируются внутри этого secure element, коммуникация с периферией — экраном, где показывается транзакция, и кнопкой, которую нажимаешь для подтверждения — всё равно проходит через незащищённый участок, через обычный процессор. Так ли это в современных дизайнах и так ли у вас?
(00:58:26) Кирилл Пименов: Это постоянная война. Штука, которая не имеет решения настолько, что для продакшена мы, по сути, скорее всего прямо склеим две Kampela в одну. Будет Kampela, которая отвечает за экран, и она не перепрошиваемая, и Kampela, которая отвечает за блокчейновую требуху, где можно ставить дополнительные прошивки. Ты не можешь secure enclave'ом контролировать экран: слишком много всего надо вычислять. По embedded-меркам памяти нужно много — надо представлять весь экран в этих точках и копировать из места в место. А enclave вообще крошечный. Если enclave не крошечный, там дыры. Поэтому ты хочешь самый маленький enclave из всех возможных. Если он крошечный, он экран не контролирует.
(00:59:08) Сергей Тихомиров: Интересно. Это рассуждение я читал много раз раньше, когда изучал тему: криптографический enclave может выполнить только очень небольшое количество операций. Почему не сделали enclave побольше или пытались и не получилось, как с SGX? Спрос, вроде, есть.
(00:59:31) Кирилл Пименов: У них есть фундаментальные проблемы с увеличением, это правда. Мы пытаемся разными подходами всё это надуть. В том числе пытаемся раздуть это до уровня дата-центра. Это технология, которая меня в платёжке очень интересует: как можно использовать secure enclave и надуть trust-элемент до полного Docker-контейнера. Подходы есть, они чудовищно сложные — такая машина Руба Голдберга. Что-то такое мы пытаемся делать. И все hardware-инженеры планеты, которые занимаются trust computing, про это сейчас очень активно думают.
(01:00:05) Кирилл Пименов: Проблема номер один. Все же знают про cold boot атаки на память. Если у тебя внешняя память с чипами и ты знаешь, что там хранятся какие-то ключи, то перед обесточиванием посреди работы процессора ты можешь залить всё жидким азотом, и память не будет такой летучей, как ты хотел, когда писалась спека. Потом можно этот чип воткнуть в специальную плату для чтения. И окажется, что мы достали из аппаратного кошелька ключ. Я точно видел на первой модели Trezor — такая атака вполне осуществлялась. У меня есть подозрение, что многие производители аппаратных кошельков недостаточно внимания уделяют этой проблеме. А они не уделяют, потому что хотят поддерживать разные странные нестандартные шифрования. А это значит, что ключ в любом случае как-то покидает enclave.
(01:01:06) Кирилл Пименов: Что делает Ledger? Ledger не позволяет запускать на Ledger свои прошивки. Надо показать прошивку Ledger Security Team, и они только разрешат. И что проверяют в первую очередь? Что ты не пользуешься root-ключом, а из enclave достаёшь только деривацию, которая соответствует твоему блокчейну. Там есть гигантская табличка: для Ethereum у нас вот такое, для Polkadot вот такое. Поэтому прошивка Polkadot, если что, сможет сбежать с ключом от Polkadot, но это никогда не скомпрометирует ключи от Ethereum и прочего.
(01:01:43) Кирилл Пименов: И это ровно то security-допущение, которое они ослабили, когда пытались сделать Ledger Recover: чтобы сделать Ledger Recover, надо было полный корневой ключ достать в общую память и что-то с ним там сделать. И даже если потом по Shamir в трёх посылках на три разных адреса зашифрованно отправлялся, так или иначе это сильное ослабление модели безопасности. За это они получили фидбек от коммьюнити, и я, если честно, даже не вспомню, в каком состоянии проект и откатили ли его совсем на редизайн.
(01:02:13) Сергей Тихомиров: То есть в Ledger Recover я правильно понимаю, что это не то, что seed-фраза шифруется внутри enclave под моим паролем и покидает его только в зашифрованном виде, а она покидает enclave в открытом виде.
(01:02:23) Кирилл Пименов: Это моё понимание того, как это могло бы работать, потому что я очень сомневаюсь, что мы можем научить имеющийся, причём далеко не во всех моделях текущего поколения, правильно шамирить, и при этом шифровать, и при этом шамирить для внешних сертификатов с каким-то certificate chain — задача настолько нетривиальная, что я бы посчитал её нерешаемой. Я не видел решения, не могу утверждать на сто процентов, но у меня возникло полное ощущение, что именно так и было.
(01:03:09) Сергей Тихомиров: Окей, хорошо, а что тогда у Kampela с соединением с экраном — оно всё равно происходит через незащищённый кусок процессора?
(01:03:19) Кирилл Пименов: Да, это так. Это одна из проблем. Поэтому мы максимально сопротивляемся тому, чтобы Kampela вообще была перепрошиваемой. Если бы моя Kampela была хорошо перепрошиваемой, я бы уже продавал её с «Ethereum, coming Q3 2025». Проблем нет. Поскольку нам надо очень много всего зафронтлоадить в места, которые мы аппаратно запретим перепрошивать… У всех процессоров есть натуральные перемычки: её как-нибудь вольтажом пережигаешь, и эти места в прошивке перестают работать. То есть перепрошивочные API перестают перепрошивать. Это требует очень внимательного дизайна, и мы не можем финализировать дизайн, пока не поймём до конца историю с метаданными перепрошивки.
(01:04:07) Кирилл Пименов: Одно из решений, на мой взгляд, сильное, но сильно мешающее в retail-цене, — тупо поставить второй процессор. Один пусть отвечает за экран, второй за NFC и связь с внешним миром. Тогда всё будет приходить по недоверенному процессору, там паковаться в понятные API, прогоняться через enclave и вылезать через второй процессор на экран, а тот процессор уже не перепрошиваемый. Значит, в том процессоре должны быть все UX-примитивы навсегда, и ты никогда не сможешь нарисовать лишнюю буковку, если не положил её в тот процессор заранее.
(01:04:40) Сергей Тихомиров: Звучит как план, я не знаю — довольно разумно.
(01:04:45) Кирилл Пименов: А это требует второго чипа, это сразу удорожает BOM примерно на 15%, потому что нужно поставить два примерно одинаковых процессора. На производстве их надо прошивать, нужен более жёсткий контроль качества и много чего ещё. Вполне может быть, что мы так и сделаем. Да, потребление питания сразу растёт, там целая куча компромиссов. Может, найдём что-то более изящное, но если что, у нас в запасе есть сильное решение, которое, к сожалению, сделает нас дороже входного Ledger — Nano S+, их сейчас продают как самые дешёвые за сто долларов. Тогда мы в сто долларов, к сожалению, не уместимся. Но в целом это валидное размышление: хотелось бы, чтобы с момента, как данные попали в secure enclave, всё, что оттуда выходит, шло только по доверенному тракту. В этом суть.
(01:05:40) Кирилл Пименов: Нам ещё несколько легче, потому что кроме перепрошиваемости и неперепрошиваемости у нас практически нет аппаратного доступа ко всему этому. Мы обладатели довольно уникальной технологии — литьё эпоксидки прямо на печатные платы. Это нетривиальная технология. Единственный массмаркет-девайс, который так умеет, — Yubikey. Даже их основной конкурент Nitrokey делает сборные корпуса. Это нетривиальная проблема чисто по физическим причинам: когда эпоксидка застывает, она либо стягивается, как зажимается, иногда на десятки процентов, либо греется — то есть либо экзотермическая, либо сдувается. Если сдувается, она начинает срывать компонент с платы просто за счёт механических напряжений. Если экзотермически оседает, могут возникнуть карманы перегрева, которые отпаивают детали. А поскольку плата уже припаяна и залита эпоксидкой, ты не можешь сделать то, что в обычном производстве электроники делают, если контроль качества не прошёл: ставят платы кверх ногами в печку, все детали падают вниз, их сортируют, каждую отдельно проверяют и в новые девайсы ставят по кругу. А у тебя сразу в шредер — и весь BOM с полной ценой никому больше не нужен, потому что один конденсатор отпаялся или перепаялся криво.
(01:07:06) Кирилл Пименов: Мы эмпирически, химическим методом нашли техпроцесс, который позволяет такого не делать. Поэтому у нас Kampela литые одним куском пластика. Половина прикольных демок, которые я обычно делаю: макаю их кому-нибудь в стакан или роняю со второго этажа на глазах у Виталика — всё это можно, потому что по факту это один довольно непрерывный кусок пластика. Механически подлезть, подпаяться, вставить бэкдор и так далее тоже весьма затруднительно. Это помогает.
(01:07:41) Сергей Тихомиров: То есть получается, что в других сайнерах, например в том же Ledger, поскольку он не залит целиком, внутри есть воздух. Технически можно его разобрать, вставить что-то внутрь и запаковать обратно так, что никто не заметит, по крайней мере без…
(01:07:58) Кирилл Пименов: Вот. Тогда же, на одном из CCC-конгрессов, где как раз презентовали большую часть атак — по-моему, это был 2019 год, я не помню точно.
(01:08:07) Сергей Тихомиров: Даже 2018, больше скажу: у нас даже был про это выпуск. Когда готовился, я посмотрел доклад, который ты кинул в наш чатик выпуска, и выпуск «Базового Блока» 053, где я пересказываю этот доклад про Wallet Fail.
(01:08:22) Кирилл Пименов: И ты же помнишь: там чувак раздавал со сцены перемычки для кнопок Ledger, которые позволяли по 433 МГц нажимать на кнопки удалённо. У меня где-то была такая штука — то ли посеял, то ли осталась в лабе, но там особо ничего нет, просто чудеса миниатюризации. Да, корпус Ledger в целом можно разобрать, и если хорошо сделать — бесследно, что-то туда вкорячить. Там есть воздух. Известная история про то, как Apple при Джобсе разрабатывала iPod: ему принесли девайс, он говорит — вы все меня обманывали? Они такие: да, точно, всё, меньше нельзя сделать. Он берёт, кидает iPod в аквариум, из него выходят пузыри: видите, там был воздух, идите миниатюризировать дальше.
(01:09:10) Сергей Тихомиров: Да, известная байка, пузыри всегда есть. Слушай, здорово. Получается, если у меня будет Kampela… Смотри, из того, что ты рассказываешь, я своими словами переформулирую два главных преимущества. Во-первых, я могу уронить с высокого этажа, окунуть в аквариум — пузырьков не будет. Во-вторых, я могу убедиться, что никто по дороге не запихнул туда кусок с удалённым доступом к нажималке кнопки без фактического нажатия — видимо, путём сравнения. Я хотел именно этот вопрос прояснить: смогу ли я зайти на сайт и посмотреть, чего ожидать.
(01:09:53) Кирилл Пименов: Это не видно радиослушателям, но мы пожертвовали размером ради наглядности. Наша печатная плата односторонняя и полностью задокументирована — не только принципиальная схема, но и разводка у нас на GitHub. При желании можно открыть. Я не помню, рендерим ли мы это сейчас в PDF или только KiCad-файлы, которые можно открыть в KiCad и посмотреть, но, кажется, и то и другое — дело техники, потому что KiCad опенсорсный, его можно бесплатно поставить на любой компьютер.
(01:10:26) Кирилл Пименов: Да, можно элемент за элементом сравнить то, что у тебя здесь, и то, что на сайте, потому что мы заливаем плату прозрачной эпоксидкой, краской не красим, и все «кишочки» наружу. В частности, можно убедиться, что на ней — и это тоже почему мы ломаемся про второй микроконтроллер — всё сделано в дискретной логике. У нас ровно два программируемых места. Это не само собой разумеется для большинства электроники, потому что проще делать крупными блоками из вещей под управлением микроконтроллера.
(01:10:54) Сергей Тихомиров: Нужно больше контекста. Расскажи, пожалуйста, про этот выбор. Для меня совершенно неочевидно, зачем так — кто сейчас произнёс.
(01:10:57) Кирилл Пименов: Тебе бы, наверное, хотелось, мне бы хотелось, чтобы в моём сайнере было поменьше мест, куда можно засунуть прошивку, которая что-то делает не так. Это и количество багов сокращает, и количество бэкдоров. Поэтому вещей, которые даже в принципе программируемы — вне зависимости от того, перебита у них эта ножка или нет, — хотелось бы поменьше. В целом наша цифровая микроэлектроника, особенно мелкосерийная, часто состоит из того, что на breadboard цепляем Arduino, на Arduino — ESP32. Это не в упрек кому-то, это очень эффективно по инженерным ресурсам. Но получается матрёшка из вещей под управлением микропроцессоров с программой. Одна программа отвечает за управление питанием, другая — за радиосвязь, отдельный чип делает NFC — и все они умные большие микросхемы с каким-то кодом на борту: closed source, откуда он пришёл, перепрошиваемый или нет — абсолютно неизвестно.
(01:11:59) Кирилл Пименов: Мы упоролись и решили это минимизировать. У нас, например, нет NFC-чипа — вообще нет микросхемы, которая умеет реализовывать NFC. Kampela по задумке не имеет внешних проводов; звёздочка — девкиты имеют, потому что после неудачной перепрошивки её надо реанимировать, там есть разъём для программатора. Розничная версия таких портов не будет. Поскольку она питается от NFC и информацию о транзакции получает по NFC, и никаких разъёмов нет, нам надо как-то реализовать NFC — мы сделали это на дискретной логике, которая гонит биты прямо в основной процессор, в основную прошивку. Нам не нужен отдельный… Жизнь была бы гораздо проще, и отладка прошивки тривиальнее, если бы мы так не делали. Но тогда у этого чипа теоретически была бы возможность ту же антенну раскачать в ответ и послать радиосигнал обратно. А Kampela вообще не умеет и не имеет технической возможности издавать радиосигналы.
(01:12:59) Сергей Тихомиров: Да, вот этот очень интересный аспект — мне тоже хотелось прояснить. Давай, может, ещё на минуту здесь остановимся. В вашей документации я прочитал, что в Kampela односторонний NFC: она получает информацию с телефона, но ничего не может отдать. Я думал, как это реализовано. Если бы вы пошли простым путём, взяли бы готовый компонент с полки — там была бы NFC в две стороны. Можно использовать, окей, но кто пишет этот код, как он там оказался и можно ли его подменить — открытый вопрос. А вы вместо этого взяли только тот кусок логики, который нужен: работа только на приём, без передачи. И прямо в железе имплементировали без опоры на внешние софтверные компоненты от кого-то?
(01:13:53) Кирилл Пименов: Это несколько преувеличение в том смысле, что софтверные компоненты всё равно в какой-то момент включаются на стороне нашей основной прошивки — там сложное помехоустойчивое кодирование и т. д. Изобразить это из транзисторов — такое себе, гораздо проще программной логикой. Всё, что превращает NFC из аналоговых радиоволн в понятный процессору цифровой сигнал, у нас сделано дискретной логикой — отдельными наборными компонентами, которые мы ставим на плату на производственной линии. С одной стороны, на рынке нет NFC-чипов, которые односторонние, потому что NFC — двусторонний протокол, как TCP: ему нужно как минимум посылать Ack-пакеты обратно. С другой стороны, мы уменьшили количество мест, которые в целом несут риск для безопасности.
(01:14:38) Сергей Тихомиров: Отправляющей стороне окей, что она Ack-пакеты не получает?
(01:14:50) Кирилл Пименов: Нет, если бы она не получала Ack-пакеты, вся штука совсем не работала бы. Поэтому в нынешней итерации Kampela прямо встроена маленькая пластиковая квадратная штучка: на борту самый дешёвый NFC-чип за пятьдесят центов, который всё время говорит «Повторите погромче, я вас не услышал» — на любой входящий запрос. Больше он ничего не делает и физически никак не связан с остальной Kampela. Эта штучка нужна, чтобы надурить телефон и всё-таки передавать информацию: иначе он что-нибудь кинет, услышит, что его никто не услышал, и из соображений экономии энергии — особенно на iPhone этим грешат — очень экономен к энергии. Вряд ли можно быть экономнее, респект этим инженерам, но этот механизм надо как-то обмануть, чтобы телефон достаточно долго и продолжительно «кричал» радиоволнами в сторону Kampela, чтобы Kampela могла использовать эти волны и шевелить точками e-ink на нашем прекрасном сенсорном экране.
(01:15:48) Сергей Тихомиров: То есть, строго говоря, какой-то NFC-сигнал идёт и в другую сторону, но он не зависит от полезной нагрузки — просто всегда говорит «говорите громче».
(01:15:54) Кирилл Пименов: Да, и он идёт не из Kampela — из отдельного внешнего девайса, который при необходимости можно подменить на любую другую карточку с поддержкой NFC и Mifare A.
(01:16:06) Сергей Тихомиров: Теперь, мне кажется, я понял лучше, что именно ты демонстрировал на демо — ссылку на которое мы приложим в описании видео, — где ты показываешь, как это работает. Момента, где ты жонглируешь тремя девайсами, я сначала не понял: телефон, карточка проезда на берлинский транспорт и Kampela. Я подумал: при чём здесь вообще Deutsche Bahn и BVG?
(01:16:34) Сергей Тихомиров: Сейчас попробую объяснить. Эта карточка телефону говорит: передавай ещё. Откуда карточка знает, что это нужно говорить?
(01:16:46) Кирилл Пименов: Телефон говорит то, что Kampela понимает, а все остальные не понимают, поэтому они отвечают: что ты мне сказал — повтори. Это случайный приятный side-эффект того, что мы не говорим на языке, который…
(01:16:56) Сергей Тихомиров: Понял. Карточка слышит, что ей что-то говорят, но она не может это расшифровать, потому что это для Kampela, а не для карточки. И карточка говорит: повтори.
(01:17:02) Кирилл Пименов: Да, смысл в том, чтобы из этого что-то извлечь.
(01:17:10) Сергей Тихомиров: Окей. Как так получается, что когда карточка или съёмный модуль Kampela говорит «повтори», телефон передаёт следующую часть сообщения, а не повторяет уже предыдущую? Или всё сообщение идёт одним куском?
(01:17:29) Кирилл Пименов: Там странный протокол поверх NFC NDEF, сделанный по стандартам, который пытается сделать канальный TCP из UDP — если такая аналогия здесь уместна, с большим натягом, но да. Смысл в том, что это просто посылка датаграмм и какая-то реакция на них, и странным образом перемешиваются аппаратно-канальный уровень и семантический. Всё, чему нас учили про модель OSI на семи слоях, — это на самом деле абстракция, и как только ты начинаешь проектировать реальные радиопротоколы, все слои слипаются.
(01:18:04) Сергей Тихомиров: То есть получается, что если протокол это предусматривает, нормальный Ack в ответ мы послать не можем, потому что он как-то закоммичен к payload, который пришёл на устройство?
(01:18:15) Кирилл Пименов: Если сейчас не супер точно из головы отвечу, как именно с точки зрения пакетов это реализовано — мне надо будет немного либо в код посмотреть, либо Flipper'ом это потыкать.
(01:18:28) Сергей Тихомиров: Просто для меня неочевидно, почему мы обратно передаём сигнал «повтори ещё», а не просто «понял, принял, шли дальше».
(01:18:38) Кирилл Пименов: Может и «понял, принял», если честно. Вообще неважно, потому что на стороне отправки ты в общем контролируешь, что дальше шлёшь. Это тоже сложность: Android шлёт достаточно пакетов, чтобы питать Kampela, а Apple начинает думать, что происходит какая-то фигня, и нужно специальное приложение, даже чтобы повторять их с достаточной частотой, чтобы Kampela раскачать. Поэтому когда я демонстрирую, мне сложнее с пользователями Apple: им надо что-то из TestFlight и прочих вещей.
(01:19:10) Кирилл Пименов: Но важно сказать, что мы используем самый простой NDEF-протокол и не используем NFC payments API и прочих настроек над ним, которые требуют дополнительной верификации с Apple и других разрешений. Самый простой — то, чем работают все NFC-токены: карточки на проезд, музеи, где можно приложить телефон, и он что-нибудь расскажет про экспонат. Это тот протокол, который мы используем — абсолютно общедоступный и понятный.
(01:19:44) Сергей Тихомиров: Завершая обзор типичного user flow, который проходит пользователь с Kampela: у меня есть payload, сформированный, допустим, телефоном, к нему приложены Merkle root metadata — то, о чём мы говорили в первой части разговора, — и это по NFC уходит на Kampela. Kampela подписывает и показывает подписанный payload в виде QR-кода на экранчике. Давай осветим этот аспект.
(01:20:12) Кирилл Пименов: Единственный способ, которым информация могла бы покидать Kampela, — это экран. Мы надурили физику, чтобы она работала на нашей стороне в обеспечении безопасности ваших ключей. Если я втыкаю куда-то USB, я, если честно, вообще не в курсе, что куда и в какую сторону идёт, и никакого общедоступного понятного sniffer'а нет. Есть большое количество супернёрдовских штук, но предлагать их использовать — это как дебажить не в Visual Studio, а в старом добром GDB с управлением с клавиатуры в терминале.
(01:20:50) Кирилл Пименов: Такого уровня никто никогда не сможет этим пользоваться, чтобы убедиться, что его аппаратный USB-ключ не тырит ключи и не рассказывает их по одному битику в подписи на протяжении двух лет. Это гораздо проще, когда у меня есть экран. Экран содержит QR-код. QR-код имеет только те биты, которые ты ждёшь. И ты можешь любой независимой камерой сосканировать этот QR-код и убедиться, что там то, что ты ждёшь, и ничего больше.
(01:21:20) Сергей Тихомиров: Подожди, а почему QR-код не может по биту за подпись сливать приватный ключ? Наверняка же там есть какой-нибудь случайный инициализирующий вектор — его в принципе можно было бы подбирать не совсем случайно.
(01:21:37) Кирилл Пименов: Совсем kleptography — это когда мы в неочевидных полях наших цифровых подписей потихоньку пытаемся слить информацию из защищённого контура. От неё физикой не защитишься, но как минимум ты можешь убедиться, что лишние байты туда не примешиваются. Да, у тебя есть какой-нибудь nonce, и более хорошие методы шифрования используют детерминированный nonce — как раз чтобы это исключить, потому что у девайса нет свободы выбирать этот nonce: он коммитится от того, что внутри payload'а.
(01:22:04) Кирилл Пименов: Но как минимум ты видишь, что там нет просто ещё одной цифры, что там нет никаких дополнительных полей — это уже хороший первый эшелон защиты. Кроме того, у QR-кода очень приятное свойство: он направленный. Пока ты его в камеру специально не ткнёшь, подпись не транслируется. Поэтому ты всегда можешь передумать, и у тебя очень естественный физический жест подтверждения транзакции — не надо нажимать кнопки и делать что-то такое. А поскольку мы используем e-ink в дисплее, QR-код на экране в общем остаётся бесконечное количество времени, и у тебя есть всё время мира, чтобы с ним что-то сделать. В момент, когда ты подписал, вывел подпись на экран — вот она там, — ты можешь с ней делать что угодно столько, сколько хочешь, а девайс уже умер. Он не просто уснул: он умер, у него нет никакого стейта. В момент, когда ты отслонил его от телефона и NFC больше в него не идёт, у него нет ни внутреннего состояния, ни лишних процессов, ни памяти — есть просто конденсаторы, которые потихоньку разряжаются в небытие.
(01:23:02) Кирилл Пименов: Понятно, что не во всех местах user flow нам нормально, что то, что мы видим на экране, остаётся там навечно. Например, если бы там была seed-фраза, я бы хотел, чтобы она стиралась. Поэтому мы следим за разрядом батареек, и когда хватает ровно на один полный wipe экрана, сверяемся с состоянием памяти: если отмечено, что экран секретный, из последних сил просто его wipe'аем. Но в большинстве мест в прошивке такого не надо.
(01:23:41) Сергей Тихомиров: Но в целом я, как пользователь, могу что-то нажать, чтобы очистить экран после того, как отсканировал.
(01:23:46) Сергей Тихомиров: На этом мы завершаем первую часть разговора с Кириллом Пименовым, CEO компании Kalapaja. В следующей части вас ждёт продолжение нашего разговора с Кириллом, главным образом о проекте платежной системы Kalatori, а также о ценностях шифропанка. Не переключайтесь.
(01:24:08) Сергей Тихомиров: И завершая эту часть нашего разговора, я ещё раз хочу поблагодарить тех, кто поддерживает наш подкаст. Это наши патроны на Patreon и Boosty, а также наши спонсоры Fluence, децентрализованная облачная платформа, Acki Nacki, самый быстрый блокчейн из теоретически возможных, 1inch, лидер DEX-агрегации, и Zerion, Enterprise-grade Web3 API. До следующего выпуска. Всем пока.