Функция cipher.NewGCM

Функция cipher.NewGCM создает новый экземпляр шифра в режиме GCM на основе переданного блочного шифра. В первый параметр мы передаем блочный шифр, реализующий интерфейс cipher.Block (например, созданный функцией aes.NewCipher). Функция возвращает интерфейс cipher.AEAD, который предоставляет методы для шифрования и расшифрования с аутентификацией. Режим GCM обеспечивает как конфиденциальность, так и целостность данных, а также позволяет аутентифицировать дополнительные данные, которые не шифруются.

Синтаксис

gocipher.NewGCM(block cipher.Block) (cipher.AEAD, error)

Пример использования с AES-256

Давайте создадим AEAD-шифр на основе AES-256 и зашифруем сообщение с аутентификацией:

gopackage main

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

func main() {
  key := make([]byte, 32)
  if _, err := io.ReadFull(rand.Reader, key); err != nil {
    panic(err)
  }

  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)
  }

  plaintext := []byte("secret message")
  ciphertext := gcm.Seal(nil, nonce, plaintext, nil)

  fmt.Printf("nonce: %x\n", nonce)
  fmt.Printf("ciphertext: %x\n", ciphertext)
}

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

go"nonce: 7f8a9b3c1d5e6f..."
"ciphertext: a1b2c3d4e5f6..."

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

Давайте расшифруем зашифрованное сообщение, используя тот же ключ и nonce:

gopackage main

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

func main() {
  keyHex := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
  key, _ := hex.DecodeString(keyHex)

  nonceHex := "7f8a9b3c1d5e6f"
  nonce, _ := hex.DecodeString(nonceHex)

  ciphertextHex := "a1b2c3d4e5f6"
  ciphertext, _ := hex.DecodeString(ciphertextHex)

  block, err := aes.NewCipher(key)
  if err != nil {
    panic(err)
  }

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

  plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
  if err != nil {
    panic(err)
  }

  fmt.Printf("decrypted: %s\n", plaintext)
}

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

go"decrypted: secret message"

Пример с дополнительными данными

Давайте продемонстрируем использование дополнительных данных, которые аутентифицируются, но не шифруются:

gopackage main

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

func main() {
  key := make([]byte, 32)
  if _, err := io.ReadFull(rand.Reader, key); err != nil {
    panic(err)
  }

  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)
  }

  plaintext := []byte("secret message")
  additionalData := []byte("public header")
  ciphertext := gcm.Seal(nil, nonce, plaintext, additionalData)

  decrypted, err := gcm.Open(nil, nonce, ciphertext, additionalData)
  if err != nil {
    panic(err)
  }

  fmt.Printf("decrypted: %s\n", decrypted)
}

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

go"decrypted: secret message"

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

  • функцию aes.NewCipher,
    которая создает новый AES-шифр
  • интерфейс cipher.AEAD,
    который предоставляет методы для аутентифицированного шифрования
  • функцию cipher.NewCTR,
    которая создает шифр в режиме CTR
  • функцию cipher.NewCBCEncrypter,
    которая создает шифр в режиме CBC для шифрования