Функция hmac.Equal

Функция hmac.Equal предназначена для безопасного сравнения двух HMAC-подписей (сообщений аутентификации кода на основе хеша). В первый параметр передается ожидаемая подпись, во второй - вычисленная подпись. Главная особенность функции заключается в том, что она выполняет сравнение за постоянное время, что исключает возможность временных атак (timing attacks), когда злоумышленник может определить правильность подписи по времени ответа сервера.

Функция принимает два аргумента типа []byte: первый - ожидаемая подпись (expected MAC), второй - вычисленная подпись (actual MAC). Возвращает bool - true, если подписи равны, и false в противном случае.

Синтаксис

gohmac.Equal(expected, actual)

Пример

Давайте создадим HMAC-подпись для сообщения с использованием SHA-256 и сравним ее с эталонной подписью:

gopackage main

import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/hex"
  "fmt"
)

func main() {
  key := []byte("secret-key")
  message := []byte("important data")

  // Создаем HMAC подпись
  h := hmac.New(sha256.New, key)
  h.Write(message)
  signature := h.Sum(nil)

  // Ожидаемая подпись (для примера используем ту же)
  expected := signature

  // Проверяем подписи
  res := hmac.Equal(expected, signature)
  fmt.Println(res)
}

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

gotrue

Пример

Теперь сравним корректную подпись с поддельной. Создадим две HMAC-подписи с разными ключами и проверим их равенство:

gopackage main

import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/hex"
  "fmt"
)

func main() {
  key1 := []byte("correct-key")
  key2 := []byte("wrong-key")
  message := []byte("secret data")

  // Создаем HMAC подпись с правильным ключом
  h1 := hmac.New(sha256.New, key1)
  h1.Write(message)
  correctSignature := h1.Sum(nil)

  // Создаем HMAC подпись с неправильным ключом
  h2 := hmac.New(sha256.New, key2)
  h2.Write(message)
  wrongSignature := h2.Sum(nil)

  // Сравниваем подписи
  res := hmac.Equal(correctSignature, wrongSignature)
  fmt.Println(res)
}

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

gofalse

Пример

Рассмотрим практический сценарий - проверка подписи сообщения при получении данных из внешнего источника. Функция hmac.Equal используется для безопасной верификации целостности и подлинности сообщения:

gopackage main

import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/hex"
  "fmt"
)

func main() {
  key := []byte("shared-secret-key")
  message := []byte("transaction data: transfer $100 to user123")
  receivedSignature, _ := hex.DecodeString("a1b2c3d4e5f6...")

  // Вычисляем подпись для полученного сообщения
  h := hmac.New(sha256.New, key)
  h.Write(message)
  computedSignature := h.Sum(nil)

  // Безопасно сравниваем подписи
  if hmac.Equal(receivedSignature, computedSignature) {
    fmt.Println("Signature valid - processing transaction")
  } else {
    fmt.Println("Invalid signature - rejecting request")
  }
}

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

go"Invalid signature - rejecting request"

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

  • функцию hmac.New,
    которая создает новый HMAC-хеш для подписи сообщений
  • функцию subtle.ConstantTimeCompare,
    которая обеспечивает сравнение байтовых массивов за постоянное время
  • функцию sha256.New,
    которая создает SHA-256 хеш для использования в HMAC
  • функцию hash.Hash,
    которая является интерфейсом для хеш-функций в пакете crypto