Вторая – это безопасность: нужно быть уверенным, что никто не сможет потратить ваши монеты, кроме вас самих.
Если кто-то получит доступ к ключу, они могут просто отправить ваши монеты себе.
Третья цель – удобство, то есть управление ключами должно быть относительно легким.
Как вы можете себе представить, достижение всех трех целей одновременно может быть проблемой.
Различные подходы к управлению ключами предлагают различные компромиссы между доступностью, безопасностью и удобством.
Самый простой способ управления ключами – хранить их в файле на своем локальном устройстве: компьютере, телефоне или каком-либо другом гаджете, который вы носите, или владеете, или управляете.
Этим достигается удобство: наличие приложения для смартфонов позволяет тратить монеты с помощью нескольких кнопок.
Но это нарушает доступность или безопасность – вы можете потерять устройство, устройство может выйти из строя, и вы можете стереть данные, или если ваш файл поврежден, ваши ключи будут потеряны, и, следовательно, вы потеряете ваши монеты.
Аналогично это нарушает обеспечение безопасности: кто-то может украсть или сломать ваше устройство или заразить вредоносным ПО, кто-то может копировать ваши ключи, а затем отправить все ваши монеты себе.
Другими словами, хранение ваших приватных ключей на локальном устройстве, особенно мобильном устройстве, очень похоже на хранение денег в вашем кошельке.
Полезно иметь некоторые карманные деньги, но вы не носите с собой все свои сбережения, потому что можете их потерять, или кто-то может их украсть.
Так что обычно вы храните немного информации / немного денег в кошельке и храните большую часть своих денег в другом месте.
Если вы храните биткойны локально, вы обычно используете программное обеспечение для кошелька, которое является программным обеспечением, отслеживающим все ваши монеты, которое управляет вашими ключами и имеет удобный пользовательский интерфейс.
Программное обеспечение кошелька позволяет вам легко использовать целую кучу разных адресов с разными ключами.
Как вы помните, создание пары публичный-приватный ключей является легким, и вы можете использовать это для своей анонимности или конфиденциальности.
Программное обеспечение кошелька дает вам простой интерфейс, который показывает вам, сколько монет в вашем кошельке.
И когда вы хотите потратить биткойны, кошелек обрабатывает детали того, какие ключи использовать и как создать новый адрес и т. д.
Чтобы тратить или получать биткойны, вам также нужен способ обмена адресом с другой стороной – адресом, которому должны быть отправлены биткойны.
Существует два основных способа кодирования адресов, которые могут быть переданы от получателя к отправителю: это передача текстовой строки или передача QR-кода.
Чтобы закодировать адрес в виде текстовой строки, мы берем биты ключа и преобразуем их из двоичного числа в число base 58.
Что означает base58?
«base» означает число символов, которые вы используете для представления числа.
В своей повседневной жизни мы пользуемся числами base10.
Чем больше символов у вас в базе, тем меньше их вам нужно использовать для представления больших чисел. Таким образом, чем больше база, тем короче число.
Почему используется base58?
58 – это усеченное количество символов алфавитно-цифрового алфавита, где есть 62 символа.
В base58 удалены плохие символы, такие как 0, O, L и I, которые легко можно спутать.
Таким образом, base58 имеет два преимущества:
Эта база дает большой набор символов, чтобы представлять большие числа в более коротком формате.
И эта база не содержит неудобные символы, чтобы вы не ошибались при расшифровке.
Например, чтобы перевести десятичное число в 58-ричное, нужно все время делить на 58, брать остаток и сопоставлять его номеру символа базы.
Таким образом, чтобы закодировать адрес в виде текстовой строки, мы берем биты публичного ключа и преобразуем их из двоичного числа в число base 58.
Затем мы используем набор из 58 символов для представления каждой цифры в качестве символа.
Однако такого ручного метода передачи адресов с помощью строк можно избежать с помощью QR-кода.
Таким образом, второй способ кодирования адреса биткойнов – это QR-код, или двумерный штрих-код.
Преимущество QR-кода заключается в том, что вы можете сфотографировать его с помощью смартфона, а программное обеспечение для кошелька может автоматически конвертировать штрих-код в последовательность бит, которая представляет соответствующий биткойн-адрес.
Хранение биткойнов на вашем компьютере или другом устройстве – аналогично тому, как перекладывать деньги из кошелька или в кошелек.
Это называется «горячее хранением».
Это удобно, но также рискованно.
С другой стороны, есть «холодное хранение», которое не подключено к Интернету, и которое заархивировано.
Такое хранение более безопасно, но, конечно, не так удобно.
Чтобы иметь отдельное горячее и холодное хранилище, вам нужно иметь отдельные секретные ключи для каждого из них – иначе монеты в холодном хранилище будут уязвимы, если горячее хранилище будет взломано.
Также вам нужно перемещать монеты туда и обратно между этими двумя хранилищами, используя публичные ключи, которые соответствуют адресам этих хранилищ.
Холодное хранилище не подключено к сети, поэтому горячее хранилище и холодное хранилище не смогут подключаться друг к другу в любом месте.
Но хорошая новость заключается в том, что холодное хранилище не обязательно должно быть онлайн для получения монет – потому что, так как горячее хранилище знает адрес холодного хранилища, оно может в любой момент отправить монеты в холодное хранилище.
В любое время, когда количество денег в вашем горячем кошельке становится слишком большим, вы можете перенести их в холодное хранилище, не подвергая его риску подключением к сети.
В следующий раз, когда холодное хранилище подключится к сети, оно сможет обновить информацию о цепочке блоков, а затем холодное хранилище сможет делать все что хочет с этими монетами.
Но есть небольшая проблема, когда дело доходит до управления адресами холодного хранилища.
С одной стороны, для конфиденциальности и других причин мы хотим иметь возможность получать каждую сумму денег по отдельному адресу со своим секретным ключом.
Поэтому всякий раз, когда мы переносим сумму денег из горячего хранилища в холодное хранилище, мы хотели бы использовать для этой цели свежий холодный адрес.
Но так как холодное хранилище не в сети, мы должны иметь какой-то способ, чтобы горячее хранилище узнала об этих адресах.
Тупым решением было бы генерация большой партии адресов одновременно холодным хранилищем и отправка их горячему хранилищу, чтобы в дальнейшем использовать их по одному.
Недостатком является то, что мы должны периодически подключать холодное хранилище, чтобы передавать дополнительно адреса.
Однако более эффективным решением является использование иерархического кошелька.
Это позволяет холодному хранилищу использовать неограниченное количество адресов, и горячему хранилищу знать об этих адресах, с помощью короткой одноразовой связью между двумя хранилищами. Но это требует немного криптографического обмана.
Прежде всего, когда мы говорили о генерации ключей и цифровых подписях, мы рассмотрели функцию, называемую generateKeys, которая генерирует открытый ключ (который действует как адрес) и секретный ключ.
В иерархическом кошельке генерация ключей работает по-другому.
Вместо того, чтобы генерировать единственный адрес, мы генерируем то, что будем называть информацией о генерации адреса, а вместо приватного ключа генерируем то, что мы будем называть информацией о генерации секретного ключа.
Учитывая информацию о генерации адреса, мы можем генерировать последовательность адресов: мы применяем функцию генерации адреса, которая принимает в качестве входных данных информацию о генерации адресов и любое целое число n и генерирует n-й адрес в последовательности.
Аналогичным образом мы можем генерировать последовательность приватных ключей с использованием информации о генерации секретного ключа.
Криптографическая магия заключается в том, что для каждого i, адрес и секретный ключ соответствуют друг другу, то есть i-й секретный ключ может использоваться для траты биткойнов с i-го адреса так же, как если бы пара была сформирована прежним способом.
Таким образом, теперь у нас есть последовательность пар ключей.
Другим важным криптографическим свойством здесь является безопасность: информация о генерации адресов не передает никакой информации о закрытых ключах.
Это означает, что безопасно предоставить информацию о генерации адресов кому угодно, и этот кто-угодно не сможет сгенерировать i-й ключ.
Теперь, не все существующие схемы цифровой подписи могут быть изменены для поддержки генерации иерархических ключей.
Но хорошей новостью является то, что схема цифровой подписи, используемая Bitcoin, ECDSA, поддерживает иерархическое генерирование ключей, что позволяет использовать этот трюк.
То есть, холодное хранилище может сгенерировать произвольное количество ключей, а горячее хранилище сгенерирует соответствующие адреса.
Холодное хранилище создает и сохраняет информацию о генерации секретного ключа и информацию о генерации адреса.
Оно создает одноразовую передачу информации о генерации адреса горячему хранилищу.
Горячее хранилище генерирует новый адрес последовательно каждый раз, когда оно хочет отправить монеты холодному хранилищу.
Когда холодное хранилище снова подключается в сеть, оно последовательно генерирует адреса и проверяет цепочку блоков для транзакций на эти адреса, пока не достигнет адреса, который не получил никаких монет.
Оно также может последовательно генерировать приватные ключи, если оно хочет отправить монеты обратно горячему хранилищу или потратить их другим способом.
Теперь давайте поговорим о различных способах хранения холодной информации – будь то один или несколько ключей, или хранение информации о генерации ключей.
Первый способ – хранить эту информацию на каком-либо устройстве и помещать это устройство в сейф.
Это может быть портативный компьютер, мобильный телефон или планшет, или флэш-накопитель.
Главное – выключить устройство и заблокировать его, чтобы, если кто-то захочет его украсть, ему придется взломать заблокированное хранилище.
Второй способ, который мы можем использовать, называется мозговым кошельком.
Это способ контролировать доступ к биткойнам, используя только секретную кодовую фразу.
Это позволяет избежать необходимости использования жестких дисков, бумаги или любого другого долговременного механизма хранения.
Это может быть особенно полезно в ситуациях, когда у вас могут украсть носитель для хранения ключей, например, когда вы путешествуете.
Мозговой кошелек основан на предсказуемом алгоритме для конвертации ключевой фразы в публичный и приватный ключи.
Например, вы можете хэшировать кодовую фразу подходящей хеш-функцией для получения приватного ключа, а с учетом приватного ключа, публичный ключ можно получить стандартным способом.
Кроме того, объединив это с иерархическим кошельком, мы можем генерировать последовательность адресов и приватных ключей из кодовой фразы, что позволяет создать полноценный кошелек.
Тем не менее, злоумышленник также может получить все приватные ключи в мозговом кошельке, если он сможет угадать кодовую фразу.
Как и всегда в компьютерной безопасности, мы должны предположить, что злоумышленник знает процедуру, которую вы использовали для генерации ключей, и только ваша кодовая фраза обеспечивает безопасность.
Таким образом, злоумышленник может использовать различные фразы и генерировать адреса, проверяя их; если он найдет какие-либо неизрасходованные транзакции в цепочке блоков по любому из этих адресов, он может немедленно потратить их для себя.
Злоумышленник может не знать, кому принадлежали монеты, и эта атака не требует взлома конкретной машины.
Угадывание кодовых фраз мозговых кошельков не направлено на конкретных пользователей, и не оставляет следов.
Кроме того, в отличие от задачи угадывания пароля электронной почты, которая может быть ограничена вашим почтовым сервером, с мозговыми кошельками, злоумышленник может загрузить список адресов с неиспользованными монетами и пробовать неограниченное число потенциальных фраз.
Обратите внимание, что здесь злоумышленнику не нужно знать, какие адреса соответствуют мозговым кошелькам.
Это называется автономным взломом пароля.
Очень сложно придумать кодовую фразу, которую легко запомнить, но которую сложно угадать.
Одним из надежных способов генерации кодовой фразы является автоматическая процедура выбора случайного 80-битного числа и конвертация этого числа в кодовую фразу так, что разные числа приводят к разным фразам.
На практике также разумно использовать преднамеренно медленную функцию для получения приватного ключа из кодовой фразы (что называется растяжкой ключей), чтобы гарантировать, что атакующему потребуется как можно больше времени для подбора фраз.
Базовый подход состоит в том, чтобы взять быструю криптографическую хеш-функцию, такую как SHA-256, и вычислить, например, 2 в 20 степени ее итераций, умножая вычислительную нагрузку атакующего на коэффициент 2 в 20 степени.
Конечно, если такое вычисление будет слишком медленным, оно начнет раздражать самого пользователя, поскольку его устройство должно быть способно вычислить эту функцию в любое время, когда пользователь захочет потратить монеты из своего мозгового кошелька.
Если кодовая фраза кошелька станет недоступной – скажем, вы ее забыли, не записали и не можете угадать – тогда монеты потеряны навсегда.
Третий вариант холодного хранения – это то, что называется бумажным кошельком.
Мы можем распечатать ключ на бумаге, а затем положить эту бумагу в безопасное место.
Очевидно, что безопасность этого метода так же хороша или плоха, как и физическая безопасность используемой бумаги.
Обычно бумажные кошельки кодируют как публичный, так и приватный ключ двумя способами: как 2D штрих-код и как строку base58.
Так же, как и с мозговым кошельком, хранение небольшого количества информации достаточно, чтобы воссоздать кошелек.
Четвертый способ холодного хранения, с помощью которого мы можем хранить информацию в автономном режиме, состоит в том, чтобы поместить его в какое-либо устройство, защищенное от доступа.
Либо мы вводим ключ в устройство, либо устройство генерирует ключ; в любом случае, устройство сконструировано таким образом, что оно не может выдавать ключ, то есть для него отсутствует функция чтения.
Вместо этого устройство подписывает транзакции с помощью ключа и делает это, когда мы, скажем, нажимаем кнопку или даем ему какой-то пароль.
Одно из преимуществ заключается в том, что, если устройство потеряно или украдено, мы это узнаем, и ключ может быть украден, только если устройство будет украдено.
Это отличается от хранения вашего ключа на ноутбуке.
Таким образом, люди могут использовать комбинацию из четырех этих методов для хранения своих ключей.
Для горячего хранения, когда хранится большое количество биткойнов, придумываются новые схемы безопасности, чтобы защитить их, и мы поговорим немного об одной из этих более сложных схем далее.
Деление ключей
До сих пор мы рассматривали различные способы хранения и управления приватными ключами, которые управляют биткойнами, но мы всегда хранили ключ в одном месте – в сейфе, в программном обеспечении или на бумаге.
Это дает нам одну точку отказа.
Если что-то пойдет не так с этим местом хранения, тогда у нас возникнут проблемы.
Мы могли бы создавать и хранить резервные копии ключей, что снижает риск потери или повреждения ключа, но увеличивает риск кражи.
Этот компромисс кажется фундаментальным.
Можем ли мы взять часть данных и сохранить их таким образом, чтобы доступность и безопасность увеличивались одновременно?
Очень хорошо, что ответ «да», и это еще один трюк, который использует криптографию, который называется делением секрета.
Идея заключается в следующем: мы хотим разделить наш приватный ключ на некоторое количество частей N.
Мы хотим сделать это таким образом, чтобы, если мы получим какое-либо количество K этих частей, мы сможем восстановить оригинальный секрет, но, если нам дадут меньше, чем K частей, тогда мы не сможем узнать что-либо об оригинальном секрете.
Учитывая это строгое требование, просто «разрезать» секрет на куски не сработает, потому что даже одна часть дает некоторую информацию о секрете.
Нам нужно что-то умнее.
Предположим, что N = 2 и K = 2.
Это означает, что мы генерируем 2 части на основе секрета, и нам нужны обе части, чтобы иметь возможность восстановить секрет.
Назовем наш секрет S, который является просто большим (скажем, 128-битным) числом.
Мы могли бы генерировать 128-битное случайное число R и сделать две части равными R и (S побитовое исключающее ИЛИ R).
По сути, мы «зашифровали» бы S одноразовым ключом R, и мы сохранили бы ключ (R) и зашифрованный текст (S ИЛИ R) в разных местах.
Ни ключ, ни зашифрованный текст сами по себе ничего не говорят о секрете.
Но, учитывая две части, мы просто собираем их вместе, чтобы восстановить секрет.
Этот трюк работает до тех пор, пока N и K будут одинаковыми – нам просто нужно будет генерировать N-1 разных случайных чисел R для первых N-1 частей, а последней частью будет секрет S – операция ИЛИ – со всеми остальными N- 1 частями.
Но если N больше K, это уже не работает, и нам нужна некоторая алгебра.
Посмотрите на слайд.
Здесь мы должны сначала сгенерировать точку (0, S) по оси Y, а затем нарисовать линию со случайным наклоном через эту точку.
Затем мы создаем точки на этой линии, сколько захотим.
Получается, что это разделение секрета S на N – количество созданных нами точек и K = 2.
Почему это работает?
Во-первых, если мы получим две из созданных точек, мы можем провести через них линию и посмотреть, где она пересечет ось Y.
Это даст нам секрет S.
С другой стороны, если у нас есть только одна точка, она ничего не говорит о секрете S, потому что наклон линии случайный.
Каждая линия в этой точке равно вероятна, и все они пересекают ось Y в разных точках.
Есть только одна тонкость.
Мы берем большое простое число P.
Так, чтобы секрет S был между 0 и P-1, включительно.
Далее мы генерируем случайное значение R, также между 0 и P-1, и создаваемые нами точки
x = 1, y = (S + R) mod P – остаток от деления
x = 2, y = (S + 2R) mod P
x = 3, y = (S + 3R) mod P
и так далее.
Секрет соответствует точке x = 0, y = (S + 0 * R) mod P, которая равна x = 0, y = S.
Таким образом, это способ сделать деление секрета с K = 2 и любым значением N.
Если N = 4, вы можете разделить свой приватный ключ на 4 части и поместить их на 4 разных устройства, чтобы, если кто-то украдет какое-либо из этих устройств, они ничего не узнают о вашем ключе.
С другой стороны, даже если два из этих устройств будут уничтожены, вы сможете восстановить ключ, используя два других устройства.
Как и было обещано, мы увеличили доступность и безопасность.
Но мы можем сделать лучше: мы можем делать деление секрета с любыми N и K, если K не больше N.
Чтобы посмотреть, как это сделать, вернемся к фигуре.
Причина, по которой мы использовали линию вместо некоторой другой кривой, состоит в том, что линия является многочленом степени 1.
Это означает, что для восстановления линии нам нужно не менее двух точек.
Если бы мы хотели сделать K = 3, мы бы использовали параболу, которая представляет собой квадратичный многочлен или многочлен степени 2.
Для построения квадратичной функции необходимы три точки.
Мы можем использовать приведенную таблицу, чтобы понять, что происходит.
Существует формула, называемая интерполяцией Лагранжа, которая позволяет восстановить многочлен степени K-1 из любых K точек на его кривой.
Поэтому, в результате всего этого у нас есть способ хранить любой секрет в виде N частей, чтобы мы были в безопасности, даже если злоумышленник узнает K-1 частей из них.
И в то же время мы можем спокойно утерять N-K частей.
Между прочим, ничего из этого не является специфическим для Биткойна.
Вы можете тайно делить свои пароли прямо сейчас и раздавать части своим друзьям или размещать их на разных устройствах.
Но никто не делает этого с секретами, такими как пароли.
Во-первых, из-за потери удобства.
А во-вторых, потому что существуют другие механизмы безопасности для важных онлайн-учетных записей, например, двухфакторная безопасность с использованием проверки SMS.
Но для Bitcoin, если вы храните свои ключи локально, у вас нет других способов обеспечить безопасность.
Невозможно ограничить доступ к адресу биткойна с помощью SMS-сообщения.
Ситуация отличается от онлайн-кошельков, о которых мы поговорим позже.
Но не принципиально – это просто переносит проблему в другое место.
В конце концов, провайдер онлайн-кошелька должен будет каким-то образом предотвратить одну точку отказа при хранении ключей.
И все равно есть проблема с делением секрета: если мы возьмем ключ, и разделим его.
Когда мы захотим использовать ключ для подписи, нам все равно нужно объединить части и пересчитать первоначальный секрет, чтобы иметь возможность подписать с этим ключом.
Точка, в которой мы объединяем все части, по-прежнему остается одной уязвимой точкой, где злоумышленник может украсть ключ.
Криптография также может решить и эту проблему: если части хранятся на разных устройствах, есть способ генерировать подписи Bitcoin децентрализованным способом, не восстанавливая при этом приватный ключ на каком-то одном устройстве.
Это называется «пороговой подписью».
Здесь наилучшим вариантом использования является кошелек с двухфакторной защитой, который соответствует случаю N = 2 и K = 2.
Скажем, вы настроили свой кошелек на разделение ключей между вашим настольным компьютером и телефоном.
Затем вы можете инициировать оплату на своем настольном компьютере, который создаст частичную подпись и отправит ее на ваш телефон.
После этого ваш телефон уведомит вас о платежных реквизитах – получателе, сумме и т. д. – и запросит подтверждение.
Если вы подтвердите данные, ваш телефон завершит подпись, используя свою долю закрытого ключа и передаст транзакцию в цепочку блоков.
Если на вашем компьютере был вирус, который пытался украсть ваши биткойны, он может инициировать транзакцию, которая отправляет деньги на адрес хакера, но затем вы получите уведомление на своем телефоне для транзакции, которую вы не разрешали, и вы не станете ее подтверждать.
Также существует совершенно другой вариант, позволяющий избежать единственной точки отказа: это мульти подпись, про которую мы говорили раньше.
Вместо того, чтобы брать один ключ и разделять его, сценарий Bitcoin напрямую позволяет вам определить, что контроль над адресом должен быть разделен между разные ключи.
Эти ключи затем могут храниться в разных местах, а подписи производятся отдельно.
Конечно, завершенная подписанная транзакция будет создана в конечном итоге на каком-то устройстве, но даже если злоумышленник будет контролировать это устройство, все, что он сможет сделать, это предотвратить трансляцию транзакции в сеть.
Он не сможет создавать валидные мульти подписи транзакций без участия других устройств.