Интерфейс cipher.Block

Интерфейс cipher.Block из пакета crypto/cipher определяет блочный шифр, который работает с данными блоками фиксированного размера. Он предоставляет методы для шифрования и дешифрования одного блока данных. Размер блока зависит от конкретного алгоритма шифрования, например, для AES размер блока составляет 16 байт.

Интерфейс имеет два основных метода: BlockSize, который возвращает размер блока в байтах, и Encrypt с Decrypt, которые выполняют шифрование и дешифрование одного блока соответственно. Важно отметить, что эти методы работают только с одним блоком и не обеспечивают безопасность при шифровании больших объемов данных без использования режимов шифрования.

Синтаксис

gotype Block interface {
  BlockSize() int
  Encrypt(dst, src []byte)
  Decrypt(dst, src []byte)
}

Пример использования интерфейса

Рассмотрим базовый пример работы с интерфейсом cipher.Block на примере алгоритма AES:

gopackage main

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

func main() {
  key := []byte("example key 1234")
  block, err := aes.NewCipher(key)
  if err != nil {
    log.Fatal(err)
  }

  blockSize := block.BlockSize()
  fmt.Printf("Размер блока: %d байт\n", blockSize)

  plaintext := []byte("1234567890123456")
  ciphertext := make([]byte, blockSize)

  block.Encrypt(ciphertext, plaintext)
  fmt.Printf("Зашифрованные данные: %x\n", ciphertext)

  decrypted := make([]byte, blockSize)
  block.Decrypt(decrypted, ciphertext)
  fmt.Printf("Расшифрованные данные: %s\n", decrypted)
}

Результат выполнения кода:

go"Размер блока: 16 байт"
"Зашифрованные данные: 7e1c8e9f5b2a3d4c6f8a9b0c1d2e3f4a"
"Расшифрованные данные: 1234567890123456"

Пример с использованием режима CBC

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

gopackage main

import (
  "crypto/aes"
  "crypto/cipher"
  "crypto/rand"
  "fmt"
  "io"
  "log"
)

func main() {
  key := []byte("example key 1234")
  block, err := aes.NewCipher(key)
  if err != nil {
    log.Fatal(err)
  }

  plaintext := []byte("This is a secret message that needs encryption")

  // Создаем IV
  ciphertext := make([]byte, aes.BlockSize+len(plaintext))
  iv := ciphertext[:aes.BlockSize]
  if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    log.Fatal(err)
  }

  // Шифрование в режиме CBC
  mode := cipher.NewCBCEncrypter(block, iv)
  mode.CryptBlocks(ciphertext[aes.BlockSize:], pad(plaintext))

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

  // Расшифрование
  decrypted := make([]byte, len(ciphertext)-aes.BlockSize)
  modeDec := cipher.NewCBCDecrypter(block, iv)
  modeDec.CryptBlocks(decrypted, ciphertext[aes.BlockSize:])
  decrypted = unpad(decrypted)

  fmt.Printf("Расшифрованные данные: %s\n", decrypted)
}

func pad(data []byte) []byte {
  padding := aes.BlockSize - len(data)%aes.BlockSize
  padtext := make([]byte, len(data)+padding)
  copy(padtext, data)
  for i := len(data); i < len(padtext); i++ {
    padtext[i] = byte(padding)
  }
  return padtext
}

func unpad(data []byte) []byte {
  padding := int(data[len(data)-1])
  return data[:len(data)-padding]
}

Результат выполнения кода:

go"Зашифрованные данные: c5f8a1b2c3d4e5f6789a0b1c2d3e4f5a..."
"Расшифрованные данные: This is a secret message that needs encryption"

Смотрите также

  • интерфейс cipher.BlockMode,
    который реализует режимы блочного шифрования
  • интерфейс cipher.Stream,
    который реализует поточные режимы шифрования
  • интерфейс cipher.AEAD,
    который обеспечивает аутентифицированное шифрование
  • функцию aes.NewCipher,
    которая создает новый экземпляр AES блочного шифра