Функция ecdsa.SignASN1

Функция ecdsa.SignASN1 создает цифровую подпись для указанного хеша с использованием алгоритма ECDSA (Elliptic Curve Digital Signature Algorithm). В первый параметр передается приватный ключ *ecdsa.PrivateKey, во второй параметр передается хеш сообщения в виде среза байтов, который должен быть подписан. Функция возвращает два значения: сигнатуру в формате ASN.1 DER (срез байтов) и ошибку, если она возникла.

В отличие от функции ecdsa.Sign, которая возвращает пару r и s как отдельные большие числа, функция SignASN1 сразу возвращает готовую сигнатуру в стандартизированном формате ASN.1, который удобен для хранения, передачи и проверки с помощью функции ecdsa.VerifyASN1.

Синтаксис

goecdsa.SignASN1(priv *ecdsa.PrivateKey, hash []byte) (signature []byte, err error)

Пример

Давайте создадим приватный ключ и подпишем хеш сообщения с использованием алгоритма SHA-256:

gopackage main

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

func main() {
  // Генерируем приватный ключ на эллиптической кривой P-256
  privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  if err != nil {
    fmt.Println("Error generating key:", err)
    return
  }

  // Сообщение, которое нужно подписать
  message := []byte("Hello, ECDSA!")

  // Вычисляем хеш сообщения SHA-256
  hash := sha256.Sum256(message)

  // Подписываем хеш
  signature, err := ecdsa.SignASN1(privateKey, hash[:])
  if err != nil {
    fmt.Println("Error signing:", err)
    return
  }

  fmt.Printf("Signature: %x\n", signature)
}

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

go"Signature: 3044022020c0d4d0a3b1c2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f800220361e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3"

Пример

Давайте подпишем хеш сообщения и проверим подпись с помощью функции ecdsa.VerifyASN1:

gopackage main

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

func main() {
  // Генерируем приватный и публичный ключи
  privateKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
  if err != nil {
    fmt.Println("Error generating key:", err)
    return
  }
  publicKey := &privateKey.PublicKey

  // Сообщение и его хеш
  message := []byte("Important data to sign")
  hash := sha256.Sum256(message)

  // Создаем подпись
  signature, err := ecdsa.SignASN1(privateKey, hash[:])
  if err != nil {
    fmt.Println("Error signing:", err)
    return
  }

  // Проверяем подпись
  valid := ecdsa.VerifyASN1(publicKey, hash[:], signature)
  if valid {
    fmt.Println("Signature is valid")
  } else {
    fmt.Println("Signature is invalid")
  }
}

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

go"Signature is valid"

Пример

Давайте обработаем ошибку, которая возникает при передаче некорректного приватного ключа:

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 {
    fmt.Println("Error generating key:", err)
    return
  }

  // Создаем некорректный хеш (слишком короткий)
  hash := []byte("short")

  // Пытаемся подписать с некорректным хешем
  _, err = ecdsa.SignASN1(privateKey, hash)
  if err != nil {
    fmt.Println("Error occurred:", err)
    return
  }
}

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

go"Error occurred: crypto/ecdsa: invalid hash length"

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

  • функцию ecdsa.VerifyASN1,
    которая проверяет подпись в формате ASN.1
  • функцию ecdsa.GenerateKey,
    которая генерирует пару приватного и публичного ключей ECDSA
  • функцию ecdsa.Sign,
    которая возвращает подпись в виде двух больших чисел r и s
  • функцию ecdsa.Verify,
    которая проверяет подпись, переданную как два больших числа