Предисловие
Работаю ассистентом в вузе (как хобби), решил написать несколько лабораторных для студентов по дисциплине «распределенные системы». В первой части будет рассказано про возможности блокчейна, структуру и ЭЦП, а во второй части про: проверку подписи, майнинг и примерную организацию сети. Отмечу, что не являюсь специалистом по распределенным системам (организация сети может быть неверной).
Структура и возможности
Блокчейн — это один из видов распределенного хранения данных, использует 3 ранее известных технологии: одноранговые сети, шифрование и базы данных. База данных представляет из себя цепочку блоков, которая специальным образом шифруется и хранится на всех узлах сети в одном и том же виде (репликация — точная копия). Весь секрет заключается в связях между блоками за счет криптографии, как следствие практически невозможно подделать информацию в блоках.
Блокчейн позволяет безопасно распространять и/или обрабатывать данные между несколькими лицами через недоверенную сеть. Данными может быть что угодно, но наиболее интересным вариантом данных является возможность передачи информации, которая требует наличия третьей доверенной стороны. Примерами такой информации являются деньги (требуют участия банка), права на собственность (требуют участия нотариуса), договор на заем и т.д. В сущности, блокчейн устраняет необходимость в участии третьего доверенного лица.
Наиболее интересные проекты, где используется блокчейн:
- Monegraph позволяет авторам закрепить права на свою работу и установить правила (и выплаты) за использования их работы;
- La Zooz это децентрализованный Uber. Предлагай свою машину, найди перевозчика без платы Uber’у;
- Augur – это онлайн букмекер. Делай ставки и получай выигрыш;
- Storj.io – это P2P хранилище данных. Сдавай свое неиспользуемое место на диске или найди самое дешевое онлайн хранилище;
- Muse – это распределенная, открытая и прозрачная база данных специально для музыкальной индустрии;
- Ripple позволяет проводить недорогие трансграничные платежи в банки;
- Golem – мировой децентрализованный суперкомпьютер с открытым кодом, доступ к которому может получить любой человек, для выполнения распределенных вычислений (от обработки изображений до проведения исследований и запуска веб-сайтов). Используя Golem, пользователи могут покупать или продавать вычислительные мощности между собой;
- Множество других криптовалют отличающихся высокой анонимностью работы, низкой стоимостью переводов, умными контрактами и т.д.
База данных
В самом простом виде база данных (БД) представляет из себя цепочку блоков, которая может быть представлена в виде файла формата JSON.
Структура блока
Каждый блок состоит из адреса, даты и времени создания, хэша и списка транзакций. Как на рисунке 1.
- Адрес – публичный ключ, генерируемый ассиметричным алгоритмом шифрования (например, RSA), на основе придуманного пользователем приватного ключа;
- Дата и время – тот момент, когда был создан блок (у транзакции тоже есть дата и время создания);
- Хэш (связующий) – вычисляется с помощью SHA512 от адреса предыдущего блока и суммы хэшей всех транзакций текущего блока, почему связующий? Потому что при его вычислении требуется адрес предыдущего блока;
- Информация — сообщение, сумма денег (криптовалюты), документы, история болезней, программный код (умные контракты) и т.д.
![](https://habrastorage.org/webt/dz/cr/lz/dzcrlzvitx18c9i6spgmzsyv75a.png)
Рисунок 1 – блокчейн из 3-ех блоков
Для простого понимания, что из себя представляет блок, достаточно представить его в виде сундука с замком, когда вы что-то хотите туда положить, то вам нужно отпереть замок ключем, этот ключ создается вами при создании блока и называется закрытый ключ.
Электронная цифровая подпись
Чтобы информацию внутри транзакций нельзя было подделать, каждая транзакция внутри блока подписывается электронной цифровой подписью (ЭЦП).
Электронно-цифровая подпись – это последовательность байтов, формируемая путем преобразования подписываемой информации по криптографическому алгоритму и предназначенная для проверки авторства электронного документа.
ЭЦП основывается на использовании асимметричного шифрования и хэш-функциях.
Кратко о методах шифрования:
- симметричное шифрование использует один и тот же ключ и для зашифровывания, и для расшифровывания;
- асимметричное шифрование использует два разных ключа: один для зашифровывания (который также называется открытым), другой для расшифровывания (называется закрытым).
В асимметричных алгоритмах шифрования, шифрование производится с помощью открытого ключа, а расшифровка с помощью закрытого.
Но в асимметричных схемах цифровой подписи подписание производится с применением закрытого ключа, а проверка подписи — с применением открытого, то есть шифруем закрытым, а проверяем открытым (“проверить” это не “расшифровать”, не путайте).
Одним из таких алгоритмов может быть RSA. Выбор ассиметричного шифрования обосновывается тем, что другие участники сети должны убедиться в том, что именно владелец блока внес изменения и подписал блок своей подписью (проверка описана во второй части).
Закрытый и открытый ключи
Закрытый (приватный) ключ генерируется самим пользователем, используется для подписи транзакций. Хранится в тайне, тот кто владеет приватным ключем имеет доступ к ячейке блокчейна, которая может быть представлена кошельком, контейнером с какими-либо данными (например, личная переписка, важные документы и т.д.).
Открытый (публичный) ключ должен быть сгенерирован на основе приватного ключа, то есть между ними есть математическая связь (открытый ключ не из головы придуман). Он может быть опубликован, более того, в блокчейне его используют как адрес блока, а также в качестве проверки подлинности подписи информации в других блоках, сторонними участниками сети. Знание открытого ключа не дает возможности определить закрытый ключ.
Алгоритм подписания информации (документа)
Для создания подписи потребуется:
- Асимметричный алгоритм шифрования (например, RSA);
- Хэш-функция (например, SHA512);
- Информация, которую собираемся подписывать.
Поскольку асимметричные алгоритмы достаточно медленные по сравнению с симметричными, то объем подписываемых данных играет большую роль и если он велик, то обычно берут хэш от подписываемых данных, а не сами данные. Хэш получают с помощью хэш-функций, например, SHA512, которая принимает на вход некую информацию и возвращает хэш определенной длины. Хэш-функция как мясорубка, можно прокрутить мясо и получить фарш, но обратно из фарша уже мясо не получишь. Таким образом, ЭЦП ставится не на сам документ, а на его хэш. Хэш-функции не являются частью алгоритма ЭЦП, поэтому в схеме может быть использована любая надёжная хэш-функция.
Этапы:
- С помощью RSA, генерируем пару публичный и приватный ключи;
- Подписываемые данные подставляем в функцию SHA512 и получаем хэш;
- Полученный хэш и закрытый ключ подставляем в функцию асимметричного шифрования RSA, то есть RSAEncode(хэш от информации, закрытый ключ), на выходе получим строку – ЭЦП.
Алгоритм подписи данных продемонстрирован на рисунке 2.
![](https://habrastorage.org/webt/qg/m_/_u/qgm__uhhxyx9uve5ad2jynjdqls.png)
Рисунок 2 — алгоритм подписи данных
Связующий хэш блока
Связующий хэш считается путем суммирования всех хэшей транзакций текущего блока и адреса предыдущего блока:
Хэш (связующий) = SHA512(block_prev_adress_hash + transaction_hash1 + transaction_hash2 + … + transaction_hashN)
Например, из рисунка 1 видно, что хэш 3-го блока вычислялся как адрес второго блока и два хэша двух внутренних транзакций:
Хэш 3 блока = SHA512(JD9100...NNBAXVB + B35BCA...H78C + A144...875D)
Именно эта особенность определяет связи между блоками в единую цепь и самое главное защищает блокчейн от подделки злоумышленниками. Допустим, если кто-то захочет “выкинуть” или вставить свой блок в середину цепочки, то блоки следующие за ним уже не пройдут проверку, т.к. их хэш основывался на адресе который хотят подменить или убрать. О том, как участники сети проверяют или следят за целостностью сети рассказано в следующей части.
Пример подписи на языке C#
Для генерации ключевой пары можно воспользоваться различными библиотеками, например, язык C# имеет встроенный пакет для работы с алгоритмами шифрования и ЭЦП.
// Создание новой пары ключей размера 1024 бит
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
// приватный ключ, представляется ввиде строки XML
string privateKey = rsa.ToXmlString(true);
// публичный ключ, редставляется ввиде строки XML
string publicKey = rsa.ToXmlString(false);
Полученный закрытый ключ следует хранить в отдельном файле, публичный же ключ является адресом блока, поэтому его хранить не нужно.
Таким образом для каждого пользователя логин – это адрес блока (публичный ключ), а пароль — это закрытый ключ, зная эти два ключа можно получить доступ к ячейке блокчейна расположенной под этим адресом и распоряжаться находящейся в ней информацией.
Подпись произвольных данных алгоритмом шифрования RSA, передаем данные и приватный ключ, получаем подпись:
private static string SignData(string data, string privateKey)
{
// Получаем объект класса RSA через провайдер
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
// Говорим, что у нас уже есть приватный ключ (например взятый из файла) и следует использовать его
rsa.FromXmlString(privateKey);
// Преобразуем символы строки в последовательность байтов
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Хэшируем наши данные с помощью SHA512 и подписываем уже полученный хэш, а сами не данные
byte[] signedByteData = rsa.SignData(byteData, CryptoConfig.MapNameToOID("SHA512"));
// Конвертируем массив байтов в строкове представление в кодировке Base64
string signedData = Convert.ToBase64String(signedByteData);
// Возвращаем ЭЦП
return signedData;
}
Задание
Необходимо реализовать ПС хранящее цепочку блоков в отдельном файле в формате JSON, при каждом добавлении нового блока или транзакции – необходимо обновлять файл.
Функции клиента:
- Регистрация нового пользователя (один блок = 1 пользователь) – то есть создать новый блок, вернуть пользователю закрытый ключ, а публичный использовать как адрес блока;
- Авторизация – доступ к ячейке блокчейна, логином является адрес блока, паролем – закрытый ключ;
- После прохождения авторизации — вставить транзакцию с произвольной информацией в блок (не в любой, а в тот к которому есть доступ);
- Просмотр списка блоков и транзакций в понятном виде.
Структура блока и транзакций должна соответствовать описанию в методическом пособии. Также необходимо в отдельном файле хранить закрытые ключи пользователей (в настоящем блокчейне закрытый ключ хранится у каждого пользователя свой, нам же нужна такая функциональность для проверки работоспособности программы).
Продолжение — проверка подписи, майнинг и примерная организация сети
Источники
Комментарии (2)
serjeant
02.02.2018 12:36Увидел слова «ДГТУ», «ПОВТиАС», потеплело на душе )) Привет от АСОиУ ))
Спасибо за статью!
ChePeter
?«Подпись произвольных данных алгоритмом шифрования RSA»
Как то не понятно, нужно пояснить.
В биткойн применяется алгоритм дискретного логарифмирования в группе порожденной эллиптической кривой — а это один из самых распространенных «блокчейнов»