Пакет crypto/cipher
Пакет crypto/cipher предоставляет интерфейсы и реализации для симметричного шифрования и дешифрования данных. Он включает поддержку различных режимов шифрования, таких как CBC (Cipher Block Chaining), CFB (Cipher Feedback), CTR (Counter), OFB (Output Feedback) и GCM (Galois/Counter Mode). Пакет работает в сочетании с блочными шифрами, такими как AES и DES, которые реализованы в пакетах crypto/aes и crypto/des.
Основные интерфейсы
Пакет определяет несколько ключевых интерфейсов для работы с шифрованием. Интерфейс Block представляет блочный шифр и содержит методы BlockSize для получения размера блока и Encrypt с Decrypt для шифрования и дешифрования отдельных блоков. Интерфейс BlockMode представляет режимы шифрования, работающие с блоками, и содержит методы BlockSize и CryptBlocks для обработки нескольких блоков. Интерфейс Stream используется для поточных режимов шифрования и содержит метод XORKeyStream, который преобразует данные потоковым способом. Интерфейс AEAD (Authenticated Encryption with Associated Data) обеспечивает аутентифицированное шифрование с дополнительными данными.
Создание шифра AES с режимом CBC
Для создания шифра с использованием режима CBC необходимо сначала создать блочный шифр с помощью aes.NewCipher, затем инициализировать режим CBC с помощью cipher.NewCBCEncrypter или cipher.NewCBCDecrypter. Вектор инициализации (IV) должен быть случайным и иметь длину, равную размеру блока шифра.
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func main() {
key := []byte("1234567890123456") // 16 bytes for AES-128
plaintext := []byte("Hello, World! This is a secret message.")
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], padPKCS7(plaintext, aes.BlockSize))
fmt.Printf("Ciphertext length: %d\n", len(ciphertext))
}
func padPKCS7(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
Результат выполнения кода:
"Ciphertext length: 64"
Использование режима GCM для аутентифицированного шифрования
Режим GCM обеспечивает шифрование с аутентификацией, что гарантирует как конфиденциальность, так и целостность данных. Для его использования необходимо создать блочный шифр и вызвать cipher.NewGCM. Nonce должен быть уникальным для каждой операции шифрования с одним и тем же ключом.
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func main() {
key := []byte("1234567890123456") // 16 bytes for AES-128
plaintext := []byte("Hello, World! This is a secret message.")
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
panic(err)
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
panic(err)
}
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
fmt.Printf("Ciphertext length: %d\n", len(ciphertext))
}
Результат выполнения кода:
"Ciphertext length: 44"
Дешифрование данных в режиме GCM
Для дешифрования данных в режиме GCM используется метод Open интерфейса AEAD. Этот метод принимает nonce, зашифрованный текст и дополнительные данные, возвращая расшифрованный текст. Важно, что nonce должен совпадать с тем, который использовался при шифровании.
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
)
func main() {
key := []byte("1234567890123456")
ciphertext := []byte{ /* зашифрованные данные из предыдущего примера */ }
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
panic(err)
}
nonceSize := gcm.NonceSize()
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
panic(err)
}
fmt.Printf("Decrypted: %s\n", string(plaintext))
}
Результат выполнения кода:
"Decrypted: Hello, World! This is a secret message."
Поточное шифрование с использованием режима CTR
Режим CTR превращает блочный шифр в поточный, что позволяет шифровать данные произвольной длины без необходимости дополнения. Для использования CTR необходимо создать блок шифра и вызвать cipher.NewCTR с начальным значением счетчика (IV). Метод XORKeyStream применяет XOR к данным потоковым образом.
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func main() {
key := []byte("1234567890123456") // 16 bytes for AES-128
plaintext := []byte("Hello, World! This is a secret message.")
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCTR(block, iv)
ciphertext := make([]byte, len(plaintext))
stream.XORKeyStream(ciphertext, plaintext)
fmt.Printf("Ciphertext length: %d\n", len(ciphertext))
}
Результат выполнения кода:
"Ciphertext length: 45"
Смотрите также
-
пакет
crypto/aes.NewCipher,
который создает новый блочный шифр AES -
интерфейс
cipher.Block,
который представляет блочный шифр с методами шифрования и дешифрования -
интерфейс
cipher.AEAD,
который предоставляет аутентифицированное шифрование с дополнительными данными -
пакет
crypto/rand,
который предоставляет криптографически безопасный генератор случайных чисел