Код
#статьи

Пишем блокчейн-блокнот на языке программирования C#

Рассказываем, для чего нужен блокчейн в программировании и как его используют, а также пишем небольшое приложение.

Иллюстрация: Merry Mary для Skillbox Media

Блокчейн — это последовательная цепочка блоков, которые защищены от подмены. А блок — это файл, содержащий информацию о предыдущих действиях, например транзакциях о переводе криптовалют. Но при этом ошибочно считать, что эта технология используется только в криптовалюте, — на самом деле применить блокчейн можно где угодно.

Разбираемся, что же такое блокчейн, и пишем приложение с его использованием.

Что такое хеширование

Прежде чем говорить про блокчейн, нужно разобраться, что такое хеширование.

Хеширование — это преобразование данных произвольной длины в битовую строку фиксированной длины. То есть мы можем взять любой текст, например книгу «451 градус по Фаренгейту», а потом зашифровать его с помощью специального алгоритма.

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

6de4c03655fdc3e982e3bfc4f055dae5064547e8b78ef951b80c94b657a5c684
Вряд ли вы узнаете, что здесь зашифровано.

Но если будет пропущена хотя бы одна запятая или какая-нибудь буква поменяет регистр, то хеш полностью изменится.

efdc5e0108e3906fea8c93efb1d9616b7a26aa26549c5d47a1b6c3fda8199ac9
И опять вы вряд ли узнаете, что здесь зашифровано.

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

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

Один из вариантов использования хешей — хранение паролей. Когда пользователь будет регистрироваться в системе, его данные будут храниться не в чистом виде, а в виде хеша.

Каждый раз, когда он будет вводить пароль, тот будет снова хешироваться, а уже потом сравниваться с тем, что записан в базе. Даже если кто-то взломает базу данных, он не узнает, какой пароль использовался. Всё, что он увидит, — это набор непонятных символов.

Как работает блокчейн

Теперь можно вернуться к блокчейну. Особенность каждого его блока — в том, что он не только захеширован, но и хранит информацию о предыдущем блоке.

Рассмотрим это на примере блокнота. Каждая запись в нём будет восприниматься как отдельный блок.

Допустим, есть вот такая первая запись:

Привет, это первая заметка!

Её хеш выглядит так:

7cb70ea12f13042dbfbbf492c20e943b2c62a1007a9921e36f5479f6aa748bc9

Вторая запись содержит в себе саму запись, а также хеш первой записи. То есть:

7cb70ea12f13042dbfbbf492c20e943b2c62a1007a9921e36f5479f6aa748bc9_разделитель_Привет, это вторая запись!

В таком виде заметка хешируется:

8af30f625141cd685dd3ad40f32b0046b562e4efd9746f8225f5a56543a0e50a

И этот хеш становится частью третьей записи.

Если мы изменим вторую запись, то её хеш станет совсем другим. Следовательно, он не будет совпадать с тем, что был записан в третью запись. То есть блокчейн позволяет нам создавать записи, которые невозможно изменить незаметно.

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

Чтобы обойти эту проблему, используется децентрализация. То есть блоки хранятся не на едином сервере, а на всех компьютерах, которые используют приложение на блокчейне.

Эта мера используется, например, в криптовалюте BitCoin. И если кто-то захочет её у вас украсть, ему придётся одновременно заменить блоки на всех компьютерах.

Для чего нужен блокчейн

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

Есть и другие варианты:

  • В блокчейне можно хранить ставки — тогда ни букмекер, ни игрок не смогут обмануть друг друга.
  • С помощью блокчейна можно проводить выборы — что исключит возможность фальсификации результатов.
  • Можно заменить нотариуса блокчейном — и заверять документы без него.

Это далеко не весь список.

Не стоит думать, что такая система надёжна на 100%. Возможны ошибки в самом программном обеспечении, которые позволят воровать данные до того, как они будут захешированы.

Пишем приложение на блокчейне на C#

Чтобы лучше понимать, как работает блокчейн, напишем приложение с использованием этой технологии. Здесь будут приведены только самые важные части кода, поэтому реализация интерфейса останется за кадром. Если же вам интересно увидеть приложение полностью, его можно найти в этом репозитории на GitHub.

Начнём с создания класса, который представляет собой блок. Назовём его Note.

В своей работе он будет использовать преобразование строки в байты и обратно, а также шифрование, поэтому нужно подключить соответствующие пространства имён:

using System.Text;
using System.Security.Cryptography;

Теперь можно приступать к работе над самим классом:

///<Summary>Заметка для блокнота, который работает на блокчейне</Summary>
class Note
{
    public static string Splitter = "_splitter_";
    private string text;
    private byte[] hash;
 
    public Note(string text)
    {
        this.text = text;
        this.hash = ComputeHash(text);
    }
 
    private byte[] ComputeHash(string text)
    {
        SHA256 sha = SHA256.Create(); //Создаём объект, который будет вычислять хеш
        byte[] textBytes = Encoding.Default.GetBytes(text); //Преобразуем текст заметки в байты
 
        return sha.ComputeHash(textBytes); //Возвращаем хеш
    }
 
    ///<Summary>Полный текст заметки</Summary>
    public string Text { get { return this.text; } }
 
    ///<Summary>Текст заметки без хеша прошлого блока</Summary>
    public string ClearText
    {
        get
        {
            return this.text.Remove(0, this.text.IndexOf(Note.Splitter) + Note.Splitter.Length);
        }
    }
 
    ///<Summary>Хеш прошлого блока</Summary>
    public string PreviousHash
    {
        get
        {
            return this.text.Remove(this.text.IndexOf(Note.Splitter));
        }
    }
 
    ///<Summary>Хеш текущего блока в виде строки</Summary>
    public string HashString
    {
        get
        {
            //При каждом получении текущего хеша нужно считать его заново
            //Так мы будем уверены, что он актуален
            var hash = ComputeHash(this.text); 
            return Encoding.Default.GetString(hash);
        }
    }
 
    ///<Summary>Хеш в виде байтов</Summary>
    public byte[] Hash { get { return this.hash; } }
 
}

Остаётся только написать программу, которая будет использовать эти блоки. Первым делом нужно создать список блоков:

List<Note> notes = new List<Note>(); //Список блоков
 
notes.Add(new Note "start" + Note.Splitter + "First note")); //Добавляем первую заметку

Потом — реализовать метод добавления новых блоков.

static void AddNote(string text, List<Note> notes)
{
    notes.Add(new Note(notes[notes.Count - 1].HashString + Note.Splitter + text));
}

Когда пользователь вводит текст для новой заметки, он передаётся в метод AddNote().Там создаётся новый блок, который содержит текст вида

Хеш предыдущего блока_разделитель_текст заметки

Созданный блок тут же добавляется в список:

Скриншот: Skillbox Media

После того как будет создано несколько заметок, можно проверить список:

Скриншот: Skillbox Media

Здесь отображается только текст заметок, но, если посмотреть на полную информацию о них, можно увидеть, что они содержат в себе хеш прошлого блока:

Хеш выглядит немного иначе, потому что конвертируется сразу в строку, а не в шестнадцатеричное число
Скриншот: Skillbox Media

Просматривать всё это вручную, чтобы проверить достоверность данных, нет смысла, потому что блоков может быть очень много. Вместо этого напишем метод валидации:

///<summary>Проверка подлинности блоков</summary>
static void ValidateNotes(List<Note> notes)
{
    for(int i = 0; i < notes.Count; i++)
    {
        if(i == 0) //Не проверять первый блок
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("0 - Valid");
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.White;
            
            //Проверяем, соответствует ли хеш, записанный в текущий блок, хешу прошлого блока
            if(@notes[i].PreviousHash == @notes[i - 1].HashString) 
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine(i + " - Valid");
            }
            else
            {
                Console.WriteLine($"\n\n | {notes[i].PreviousHash} | {notes[i - 1].HashString} | \n\n");
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(i + " - Changed");
            }
        }
    }
 
    Console.WriteLine("\n");
}

Теперь можно проверить, всё ли в порядке с заметками, которые мы сохранили:

Скриншот: Skillbox Media

Если же в каком-нибудь блоке изменится хоть один символ, это сразу станет ясно. Поэтому такой блокнот — идеальный вариант для хранения долговых расписок и другой подобной информации.

Заключение

Это только малая часть того, что можно узнать по этой теме. Мы написали приложение, которое использует блокчейн, и использовали главный принцип блокчейна — последовательность хеширования данных.

Если же вы хотите изучить тему глубже, советую почитать статью на Habr. Там же есть ссылка на учебник по защите информации.



Онлайн-школа для детей Skillbox Kids
Учим детей программированию, созданию игр, сайтов и дизайну. Первое занятие бесплатно! Подробности — по клику.
Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована