Функция ecdsa.Verify

Функция ecdsa.Verify проверяет, является ли цифровая подпись действительной для указанного хеша с использованием открытого ключа. В первый параметр передается указатель на структуру ecdsa.PublicKey, содержащую открытый ключ. Во второй параметр передается хеш сообщения в виде среза байт. В третий и четвертый параметры передаются компоненты подписи r и s в виде срезов байт. Функция возвращает true, если подпись действительна, и false в противном случае.

Синтаксис

goecdsa.Verify(pub *ecdsa.PublicKey, hash []byte, r []byte, s []byte) bool

Пример

Создадим пару ключей ECDSA на кривой P-256 и проверим подпись для сообщения:

gopackage main

import (
  "crypto/ecdsa"
  "crypto/elliptic"
  "crypto/rand"
  "crypto/sha256"
  "fmt"
  "math/big"
)

func main() {
  // Генерируем ключи
  privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  if err != nil {
    panic(err)
  }
  publicKey := &privateKey.PublicKey

  // Сообщение и хеш
  msg := []byte("hello")
  hash := sha256.Sum256(msg)

  // Подписываем сообщение
  r, s, err := ecdsa.Sign(rand.Reader, privateKey, hash[:])
  if err != nil {
    panic(err)
  }

  // Проверяем подпись
  res := ecdsa.Verify(publicKey, hash[:], r.Bytes(), s.Bytes())
  fmt.Println(res)
}

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

gotrue

Пример

Проверим подпись с измененными данными. Подпись становится недействительной, если изменить хотя бы один байт сообщения:

gopackage main

import (
  "crypto/ecdsa"
  "crypto/elliptic"
  "crypto/rand"
  "crypto/sha256"
  "fmt"
)

func main() {
  // Генерируем ключи
  privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  if err != nil {
    panic(err)
  }
  publicKey := &privateKey.PublicKey

  // Оригинальное сообщение
  msg := []byte("hello")
  hash := sha256.Sum256(msg)

  // Подписываем оригинальное сообщение
  r, s, err := ecdsa.Sign(rand.Reader, privateKey, hash[:])
  if err != nil {
    panic(err)
  }

  // Изменяем сообщение
  msg2 := []byte("hellox")
  hash2 := sha256.Sum256(msg2)

  // Проверяем подпись с измененным хешем
  res := ecdsa.Verify(publicKey, hash2[:], r.Bytes(), s.Bytes())
  fmt.Println(res)
}

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

gofalse

Пример

Верификация подписи с использованием компонент r и s в формате ASN.1. Функция ecdsa.Verify работает с байтовыми срезами, а не со структурами:

gopackage main

import (
  "crypto/ecdsa"
  "crypto/elliptic"
  "crypto/rand"
  "crypto/sha256"
  "encoding/asn1"
  "fmt"
)

type Signature struct {
  R, S *big.Int
}

func main() {
  // Генерируем ключи
  privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  if err != nil {
    panic(err)
  }
  publicKey := &privateKey.PublicKey

  // Сообщение и хеш
  msg := []byte("hello")
  hash := sha256.Sum256(msg)

  // Подписываем и получаем ASN.1 подпись
  signatureASN1, err := ecdsa.SignASN1(rand.Reader, privateKey, hash[:])
  if err != nil {
    panic(err)
  }

  // Декодируем ASN.1 для получения r и s
  var sig Signature
  _, err = asn1.Unmarshal(signatureASN1, &sig)
  if err != nil {
    panic(err)
  }

  // Проверяем подпись
  res := ecdsa.Verify(publicKey, hash[:], sig.R.Bytes(), sig.S.Bytes())
  fmt.Println(res)
}

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

gotrue

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

  • функцию ecdsa.Sign,
    которая создает цифровую подпись ECDSA
  • функцию ecdsa.GenerateKey,
    которая генерирует пару ключей ECDSA
  • функцию ecdsa.VerifyASN1,
    которая проверяет подпись в формате ASN.1
  • пакет crypto/elliptic,
    который предоставляет кривые для ECDSA