Это часть 1/3 — скоро будут части 2 и 3!

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

Основная библиотека, которую мы будем использовать, — это реализация NaCL потока шифрования с секретным ключом. Авторы этого пакета описывают свой SecretBox так:

Пакет secretbox шифрует и аутентифицирует небольшие сообщения.

Secretbox использует XSalsa20 и Poly1305 для шифрования и аутентификации сообщений с помощью криптографии с секретным ключом.

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

Итак, прежде чем мы углубимся в код, вот краткая теория того, что мы на самом деле делаем. На приведенной ниже диаграмме показан процесс шифрования. По сути, мы начинаем с трех частей информации — Nonce, Key и Message, а в ответ мы получаем зашифрованную информацию. Сообщение.

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

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

Ононс.Ононс фактически является отвлекающим маневром. Это вносит некоторую случайность в серию зашифрованных сообщений и помогает избежать атак типа Replay Attacks. По определению, одноразовый номер (Числоиспользуется только один раз) никогда не должен повторяться и должен генерироваться случайным образом с каждым новым сообщением.

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

Таким образом, как только у нас есть наше Зашифрованное сообщение, мы передаем его вместе с нашим Ключом (очевидно, это должен быть тот же ключ, который мы использовали для шифрования) и предполагая, что нет ничего, что могло бы пойдет не так — мы получим наше исходное Сообщение обратно!

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

По сути, то, что мы делаем здесь, — это проверка ошибок в типе ошибки err, и если мы видим ошибку, мы panic наше приложение и пользовательское message возвращается вместе с самим сообщением об ошибке.

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

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

Далее нам нужно создать наш Nonce, который мы будем использовать как часть шифрования. Здесь мы добавили NonceSize к нашим константам, чтобы наш одноразовый номер всегда имел постоянную длину. Возможно, пока неясно, что мы делаем с этим одноразовым номером, но сейчас важно знать, что мы будем генерировать новый с каждым сообщением, которое хотим зашифровать, и вы можете быть уверены, что оно будет случайным — но всегда одинаковой длины.

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

Этого пока достаточно. Во второй части мы напишем функцию шифрования, которая может принимать такие значения, как JSON, строки и другие данные, которые мы хотим зашифровать.

Спасибо за чтение!