логотип PurpleSchool
логотип PurpleSchool

Пакеты crypto в Go

Автор

Александр Гольцман

Пакеты из семейства crypto в языке программирования Go (или Golang) предоставляют обширный набор инструментов для шифрования, хеширования, подписей, а также работы с TLS и криптографически стойкими случайными числами. Это ключевые компоненты при создании безопасных веб-приложений, реализации протоколов шифрования и защите данных.

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

Обзор пакетов crypto

Стандартная библиотека Go содержит несколько пакетов для разных криптографических задач. Смотрите, как они делятся по функционалу:

  • Хеширование:
    • crypto/md5, crypto/sha1, crypto/sha256, crypto/sha512 — для вычисления хеш-сумм.
    • crypto/hmac — для HMAC-подписей, которые гарантируют целостность и аутентификацию данных.
  • Шифрование:
    • crypto/aes — симметричное шифрование по стандарту AES.
    • crypto/des — шифрование по алгоритму DES (менее безопасно и редко используется).
  • Асимметричная криптография:
    • crypto/rsa — работа с ключами RSA для шифрования и цифровых подписей.
    • crypto/ecdsa — поддержка эллиптических кривых.
  • Генерация случайных чисел:
    • crypto/rand — получение криптографически стойких случайных байтов.
  • TLS-соединения:
    • crypto/tls — реализация TLS-протокола, используемая в HTTPS и других защищённых соединениях.

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

Хеширование данных

Хеш-функции создают "отпечаток" (hash) исходного сообщения. Хеш помогает быстро сверять данные и гарантировать их неизменность.

  • SHA-256, SHA-512 — надёжные алгоритмы хеширования для контрольных сумм.
  • MD5, SHA-1 — устаревшие алгоритмы, используйте их только в нетребовательных задачах, так как они уязвимы к коллизиям.

Покажу на примере, как вычислить SHA-256 хеш строки:

package main

import (
    "crypto/sha256"
    "fmt"
)

func main() {
    data := []byte("Hello, Golang!")
    hash := sha256.Sum256(data)
    fmt.Printf("%x\n", hash)
}

Здесь я размещаю строку в data, а sha256.Sum256 возвращает массив байтов, представляющий хеш.

HMAC для целостности и аутентификации

HMAC (Hash-based Message Authentication Code) позволяет проверять, не были ли изменены данные при передаче. Смотрите, как создать HMAC на основе SHA-256:

package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "fmt"
)

func main() {
    key := []byte("secret-key")
    message := []byte("Hello, HMAC!")

    h := hmac.New(sha256.New, key)
    h.Write(message)
    signature := h.Sum(nil)

    fmt.Printf("%x\n", signature)
}

При проверке HMAC вы вычисляете подпись на другой стороне и сверяете её с полученной, что гарантирует целостность и аутентификацию данных.

Симметричное шифрование AES

Алгоритм AES считается одним из самых надёжных. В Go он реализован в пакете crypto/aes. Симметричное шифрование использует один ключ для шифрования и расшифрования.

Пример шифрования данных:

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "fmt"
)

func main() {
    key := []byte("examplekey123456") // 16, 24 или 32 байта
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    plaintext := []byte("Hello, AES!")
    ciphertext := make([]byte, len(plaintext))

    // ECB-режим в Go не встроен, но для примера
    // показываю блоковое шифрование без режима.
    block.Encrypt(ciphertext, plaintext)

    fmt.Printf("Зашифрованный текст: %x\n", ciphertext)
}

На практике стоит использовать режимы шифрования (CBC, GCM), чтобы обеспечить безопасность (например, crypto/cipher.NewGCM).

Асимметричная криптография (RSA)

Асимметричное шифрование и цифровые подписи позволяют использовать пару ключей: публичный и приватный. В Go для этого есть пакет crypto/rsa.

privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
    panic(err)
}
publicKey := &privateKey.PublicKey

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

TLS-соединения

Веб-приложения и микросервисы часто используют HTTPS. Пакет crypto/tls позволяет создавать защищённые соединения.

srv := &http.Server{
    Addr:    ":443",
    Handler: myHandler,
    TLSConfig: &tls.Config{
        // настройки TLS
    },
}
srv.ListenAndServeTLS("cert.pem", "key.pem")

Смотрите, здесь я разместил пример HTTPS-сервера. Он требует сертификата cert.pem и приватного ключа key.pem, которые можно сгенерировать с помощью OpenSSL.

Генерация случайных чисел

Для криптографии нужны стойкие случайные значения. В Go их предоставляет crypto/rand.

package main

import (
    "crypto/rand"
    "fmt"
    "math/big"
)

func main() {
    n, _ := rand.Int(rand.Reader, big.NewInt(100))
    fmt.Println("Случайное число:", n)
}

crypto/rand генерирует действительно случайные байты, в отличие от math/rand, который выдаёт псевдослучайные числа.

Заключение

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

Смотрите, что важно учесть:

  • Используйте SHA-256, SHA-512 и HMAC для проверки целостности данных.
  • Применяйте AES для симметричного шифрования, а RSA — для асимметричного.
  • При работе с HTTPS и защищёнными соединениями используйте TLS.
  • Генерируйте случайные числа с помощью crypto/rand.

Эти пакеты позволяют создавать надёжные и безопасные приложения, защищая данные от подделки, перехвата и несанкционированного доступа.

Стрелочка влевоРабота с временными интервалами (duration) в GolangПакет Context в GoСтрелочка вправо

Все гайды по Golang

Работа с YAML в GolangПреобразование типов в GolangКонвертация структур в JSON в GolangStrconv в GolangИспользование пакета SQLx для работы с базами данных в GolangРазбираемся с SQL в GolangРазделение строк с помощью функции split в GolangSort в GoПоиск и замена строк в Go - GolangИспользование пакета reflect в GolangРабота с PostgreSQL в GoPointers в GolangПарсинг в GoРабота со списками (list) в GolangПреобразование int в string в GolangРабота с числами с плавающей точкой в GolangРабота с полями в GolangИспользование enum в GolangОбработка JSON в GoЧтение и запись CSV-файлов в GolangРабота с cookie в GolangРегистры в GoКэширование данных в GolangПреобразование byte в string в GolangByte в GoИспользование bufio для работы с потоками данных в GolangДобавление данных и элементов (add) в Go
Логирование в Golang. Zap, Logrus, Loki, GrafanaРабота с Docker-контейнерами в GoИспользование pprof в GolangМеханизмы синхронизации в GolangРабота с пакетом S3 в GolangМониторинг Golang приложений с помощью PrometheusОптимизация проектов на GoПаттерны проектирования в GolangМиграции базы данных в GolangОркестрация контейнеров Go с Kubernetes + DockerGjGo Playground и компилятор GolangИспользование go mod init для создания модулей GolangРабота с переменными окружения (env) в GolangКоманда go build в GolangАвтоматизация Golang проектов — CI/CD с GitLab CI и JenkinsОтладка кода в GolangЧтение и использование конфигурации в приложениях на GolangКомпиляция в GolangКак развернуть Go-приложение на облаке AWSАутентификация в Golang
Сетевые протоколы в GoПеременные в GolangЗначения в GolangДженерик %T и его применение в GolangТипы данных в GolangИспользование tls в GolangИспользование tag в структурах GolangSwitch в GoСтроки в GolangРабота с потоками (stream) в GolangSelect в GoРуны в GoРабота с пакетом params в GolangКонвертация строк в числа в GolangNull, Nil, None, 0 в GoНаименования переменных, функций и структур в GoInt в GolangУстановка GolangЧтение и установка HTTP заголовков в GolangMethods в GolangGoLand — IDE для разработки на Golang от JetBrainsОбработка «not found» в GolangFloat в GolangФлаги командной строки в Go (Golang)Запуск внешних команд в GolangОбработка ошибок в GoИспользование defer в GolangЗначения default в GolangГенерация кода в GoФорматирование кода в GolangЧистая архитектура в GolangКаналы (channels) в GolangПолучение body из HTTP запроса в Golang
Открыть базу знаний