Криптография в Go (Golang): шифрование и хеширование

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Криптография в Go (Golang): шифрование и хеширование данных

Язык Go (Golang) предоставляет мощную и элегантную стандартную библиотеку для криптографических операций. В отличие от многих других языков, где требуется установка сторонних пакетов, Go включает поддержку симметричного и асимметричного шифрования, а также современных алгоритмов хеширования прямо "из коробки". В этой статье мы подробно разберем, как использовать криптографию в Go для защиты данных на образовательном портале pythonlib.ru.

Основные пакеты криптографии в Go

Вся криптография в Go сосредоточена в пакете crypto и его подпакетах. Вот ключевые из них:

  • crypto/aes — реализация Advanced Encryption Standard (AES).
  • crypto/cipher — интерфейсы для режимов шифрования (CBC, GCM, CTR).
  • crypto/rsa — асимметричное шифрование RSA.
  • crypto/sha256, crypto/sha512 — хеш-функции семейства SHA-2.
  • golang.org/x/crypto/bcrypt — адаптивное хеширование паролей (дополнительный пакет).
  • crypto/rand — криптостойкий генератор случайных чисел.

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

Симметричное шифрование использует один и тот же ключ для шифрования и расшифровки. Рассмотрим пример с AES-256 в режиме GCM (Galois/Counter Mode), который обеспечивает аутентификацию данных.

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "encoding/hex"
    "fmt"
    "io"
)

func encryptAES(plaintext []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }

    // Создаем GCM (Galois/Counter Mode)
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }

    // Генерируем случайный nonce (число, используемое один раз)
    nonce := make([]byte, gcm.NonceSize())
    if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
        return nil, err
    }

    // Seal добавляет nonce в начало зашифрованного текста
    ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
    return ciphertext, nil
}

func decryptAES(ciphertext []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }

    gcm, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }

    nonceSize := gcm.NonceSize()
    if len(ciphertext) < nonceSize {
        return nil, fmt.Errorf("ciphertext too short")
    }

    nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
    plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
    if err != nil {
        return nil, err
    }
    return plaintext, nil
}

func main() {
    key := []byte("examplekey123456") // 16 байт для AES-128
    plaintext := []byte("Секретные данные для PythonLib")

    encrypted, _ := encryptAES(plaintext, key)
    fmt.Println("Зашифровано (hex):", hex.EncodeToString(encrypted))

    decrypted, _ := decryptAES(encrypted, key)
    fmt.Println("Расшифровано:", string(decrypted))
}

Обратите внимание: ключ должен быть длиной 16, 24 или 32 байта для AES-128, AES-192 или AES-256 соответственно. Nonce (IV) генерируется случайным образом и сохраняется вместе с шифротекстом.

Асимметричное шифрование RSA в Go

RSA использует пару ключей: открытый (public) для шифрования и закрытый (private) для расшифровки. Это идеально для безопасного обмена данными между сервером и клиентом.

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "fmt"
)

func generateKeyPair(bits int) (*rsa.PrivateKey, error) {
    privateKey, err := rsa.GenerateKey(rand.Reader, bits)
    if err != nil {
        return nil, err
    }
    return privateKey, nil
}

func encryptRSA(publicKey *rsa.PublicKey, plaintext []byte) ([]byte, error) {
    // Используем OAEP (Optimal Asymmetric Encryption Padding)
    ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader                    

Рекомендаций