Криптография в 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