dsig

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 18, 2025 License: MIT Imports: 15 Imported by: 3

README

github.com/lestrrat-go/dsig CI Go Reference codecov.io

Go module providing low-level digital signature operations.

While there are many standards for generating and verifying digital signatures, the core operations are virtually the same. This module implements the core functionality of digital signature generation / verifications in a framework agnostic way.

Features

  • RSA signatures (PKCS1v15 and PSS)
  • ECDSA signatures (P-256, P-384, P-521)
  • EdDSA signatures (Ed25519, Ed448)
  • HMAC signatures (SHA-256, SHA-384, SHA-512)
  • Support for crypto.Signer interface
  • Allows for dynamic additions of algorithms in limited cases.

SYNOPSIS

package examples_test

import (
  "crypto/ecdsa"
  "crypto/ed25519"
  "crypto/elliptic"
  "crypto/rand"
  "crypto/rsa"
  "fmt"

  "github.com/lestrrat-go/dsig"
)

func Example() {
  payload := []byte("hello world")

  // RSA signing and verification
  {
    privKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
      fmt.Printf("failed to generate RSA key: %s\n", err)
      return
    }

    // Sign with RSA-PSS SHA256
    signature, err := dsig.Sign(privKey, dsig.RSAPSSWithSHA256, payload, nil)
    if err != nil {
      fmt.Printf("failed to sign with RSA: %s\n", err)
      return
    }

    // Verify with RSA-PSS SHA256
    err = dsig.Verify(&privKey.PublicKey, dsig.RSAPSSWithSHA256, payload, signature)
    if err != nil {
      fmt.Printf("failed to verify RSA signature: %s\n", err)
      return
    }
  }

  // ECDSA signing and verification
  {
    privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    if err != nil {
      fmt.Printf("failed to generate ECDSA key: %s\n", err)
      return
    }

    // Sign with ECDSA P-256 SHA256
    signature, err := dsig.Sign(privKey, dsig.ECDSAWithP256AndSHA256, payload, nil)
    if err != nil {
      fmt.Printf("failed to sign with ECDSA: %s\n", err)
      return
    }

    // Verify with ECDSA P-256 SHA256
    err = dsig.Verify(&privKey.PublicKey, dsig.ECDSAWithP256AndSHA256, payload, signature)
    if err != nil {
      fmt.Printf("failed to verify ECDSA signature: %s\n", err)
      return
    }
  }

  // EdDSA signing and verification
  {
    pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
    if err != nil {
      fmt.Printf("failed to generate Ed25519 key: %s\n", err)
      return
    }

    // Sign with EdDSA
    signature, err := dsig.Sign(privKey, dsig.EdDSA, payload, nil)
    if err != nil {
      fmt.Printf("failed to sign with EdDSA: %s\n", err)
      return
    }

    // Verify with EdDSA
    err = dsig.Verify(pubKey, dsig.EdDSA, payload, signature)
    if err != nil {
      fmt.Printf("failed to verify EdDSA signature: %s\n", err)
      return
    }
  }

  // HMAC signing and verification
  {
    key := []byte("secret-key")

    // Sign with HMAC SHA256
    signature, err := dsig.Sign(key, dsig.HMACWithSHA256, payload, nil)
    if err != nil {
      fmt.Printf("failed to sign with HMAC: %s\n", err)
      return
    }

    // Verify with HMAC SHA256
    err = dsig.Verify(key, dsig.HMACWithSHA256, payload, signature)
    if err != nil {
      fmt.Printf("failed to verify HMAC signature: %s\n", err)
      return
    }
  }
  // OUTPUT:
}

source: examples/dsig_readme_example_test.go

Supported Algorithms

Constant Algorithm Key Type
HMACWithSHA256 HMAC using SHA-256 []byte
HMACWithSHA384 HMAC using SHA-384 []byte
HMACWithSHA512 HMAC using SHA-512 []byte
RSAPKCS1v15WithSHA256 RSA PKCS#1 v1.5 using SHA-256 *rsa.PrivateKey / *rsa.PublicKey
RSAPKCS1v15WithSHA384 RSA PKCS#1 v1.5 using SHA-384 *rsa.PrivateKey / *rsa.PublicKey
RSAPKCS1v15WithSHA512 RSA PKCS#1 v1.5 using SHA-512 *rsa.PrivateKey / *rsa.PublicKey
RSAPSSWithSHA256 RSA PSS using SHA-256 *rsa.PrivateKey / *rsa.PublicKey
RSAPSSWithSHA384 RSA PSS using SHA-384 *rsa.PrivateKey / *rsa.PublicKey
RSAPSSWithSHA512 RSA PSS using SHA-512 *rsa.PrivateKey / *rsa.PublicKey
ECDSAWithP256AndSHA256 ECDSA using P-256 and SHA-256 *ecdsa.PrivateKey / *ecdsa.PublicKey
ECDSAWithP384AndSHA384 ECDSA using P-384 and SHA-384 *ecdsa.PrivateKey / *ecdsa.PublicKey
ECDSAWithP521AndSHA512 ECDSA using P-521 and SHA-512 *ecdsa.PrivateKey / *ecdsa.PublicKey
EdDSA EdDSA using Ed25519 or Ed448 ed25519.PrivateKey / ed25519.PublicKey

Description

This library provides low-level digital signature operations. It does minimal parameter validation for performance, uses strongly typed APIs, and has minimal dependencies.

Contributions

Issues

For bug reports and feature requests, please include failing tests when possible.

Pull Requests

Please include tests that exercise your changes.

Documentation

Overview

Package dsig provides digital signature operations for Go. It contains low-level signature generation and verification tools that can be used by other signing libraries

The package follows these design principles: 1. Does minimal checking of input parameters (for performance); callers need to ensure that the parameters are valid. 2. All exported functions are strongly typed (i.e. they do not take `any` types unless they absolutely have to). 3. Does not rely on other high-level packages (standalone, except for internal packages).

Index

Constants

View Source
const (
	// HMAC signature algorithms
	// These use Hash-based Message Authentication Code with specified hash functions
	HMACWithSHA256 = "HMAC_WITH_SHA256"
	HMACWithSHA384 = "HMAC_WITH_SHA384"
	HMACWithSHA512 = "HMAC_WITH_SHA512"

	// RSA signature algorithms with PKCS#1 v1.5 padding
	// These use RSA signatures with PKCS#1 v1.5 padding and specified hash functions
	RSAPKCS1v15WithSHA256 = "RSA_PKCS1v15_WITH_SHA256"
	RSAPKCS1v15WithSHA384 = "RSA_PKCS1v15_WITH_SHA384"
	RSAPKCS1v15WithSHA512 = "RSA_PKCS1v15_WITH_SHA512"

	// RSA signature algorithms with PSS padding
	// These use RSA signatures with Probabilistic Signature Scheme (PSS) padding
	RSAPSSWithSHA256 = "RSA_PSS_WITH_SHA256"
	RSAPSSWithSHA384 = "RSA_PSS_WITH_SHA384"
	RSAPSSWithSHA512 = "RSA_PSS_WITH_SHA512"

	// ECDSA signature algorithms
	// These use Elliptic Curve Digital Signature Algorithm with specified curves and hash functions
	ECDSAWithP256AndSHA256 = "ECDSA_WITH_P256_AND_SHA256"
	ECDSAWithP384AndSHA384 = "ECDSA_WITH_P384_AND_SHA384"
	ECDSAWithP521AndSHA512 = "ECDSA_WITH_P521_AND_SHA512"

	// EdDSA signature algorithms
	// These use Edwards-curve Digital Signature Algorithm (supports Ed25519 and Ed448)
	EdDSA = "EDDSA"
)

Variables

This section is empty.

Functions

func IsVerificationError

func IsVerificationError(err error) bool

IsVerificationError checks if the given error is a verification error.

func NewVerificationError

func NewVerificationError(message string) error

NewVerificationError creates a new verification error with the given message.

func PackECDSASignature

func PackECDSASignature(r *big.Int, sbig *big.Int, curveBits int) ([]byte, error)

PackECDSASignature packs the r and s values from an ECDSA signature into a JWS-format byte slice. The output format follows RFC 7515: r||s as fixed-length byte arrays.

func RegisterAlgorithm

func RegisterAlgorithm(name string, info AlgorithmInfo) error

RegisterAlgorithm registers a new digital signature algorithm with the specified family and metadata.

info.Meta should contain extra metadata for some algorithms. Currently HMAC, RSA, and ECDSA family of algorithms need their respective metadata (HMACFamilyMeta, RSAFamilyMeta, and ECDSAFamilyMeta). Metadata for other families are ignored.

func Sign

func Sign(key any, alg string, payload []byte, rr io.Reader) ([]byte, error)

Sign generates a digital signature using the specified key and algorithm.

This function loads the signer registered in the dsig package _ONLY_. It does not support custom signers that the user might have registered.

rr is an io.Reader that provides randomness for signing. If rr is nil, it defaults to rand.Reader. Not all algorithms require this parameter, but it is included for consistency. 99% of the time, you can pass nil for rr, and it will work fine.

func SignCryptoSigner

func SignCryptoSigner(signer crypto.Signer, raw []byte, h crypto.Hash, opts crypto.SignerOpts, rr io.Reader) ([]byte, error)

SignCryptoSigner generates a signature using a crypto.Signer interface. This function can be used for hardware security modules, smart cards, and other implementations of the crypto.Signer interface.

rr is an io.Reader that provides randomness for signing. If rr is nil, it defaults to rand.Reader.

Returns the signature bytes or an error if signing fails.

func SignECDSA

func SignECDSA(key *ecdsa.PrivateKey, payload []byte, h crypto.Hash, rr io.Reader) ([]byte, error)

SignECDSA generates an ECDSA signature for the given payload using the specified private key and hash. The raw parameter should be the pre-computed signing input (typically header.payload).

rr is an io.Reader that provides randomness for signing. if rr is nil, it defaults to rand.Reader.

func SignECDSACryptoSigner

func SignECDSACryptoSigner(signer crypto.Signer, raw []byte, h crypto.Hash, rr io.Reader) ([]byte, error)

SignECDSACryptoSigner generates an ECDSA signature using a crypto.Signer interface. This function works with hardware security modules and other crypto.Signer implementations. The signature is converted from ASN.1 format to JWS format (r||s).

rr is an io.Reader that provides randomness for signing. If rr is nil, it defaults to rand.Reader.

func SignEdDSA

func SignEdDSA(key ed25519.PrivateKey, payload []byte) ([]byte, error)

SignEdDSA generates an EdDSA (Ed25519) signature for the given payload. The raw parameter should be the pre-computed signing input (typically header.payload). EdDSA is deterministic and doesn't require additional hashing of the input.

func SignHMAC

func SignHMAC(key, payload []byte, hfunc func() hash.Hash) ([]byte, error)

SignHMAC generates an HMAC signature for the given payload using the specified hash function and key. The raw parameter should be the pre-computed signing input (typically header.payload).

func SignRSA

func SignRSA(key *rsa.PrivateKey, payload []byte, h crypto.Hash, pss bool, rr io.Reader) ([]byte, error)

SignRSA generates an RSA signature for the given payload using the specified private key and options. The raw parameter should be the pre-computed signing input (typically header.payload). If pss is true, RSA-PSS is used; otherwise, PKCS#1 v1.5 is used.

The rr parameter is an optional io.Reader that can be used to provide randomness for signing. If rr is nil, it defaults to rand.Reader.

func UnpackASN1ECDSASignature

func UnpackASN1ECDSASignature(signed []byte, r, s *big.Int) error

UnpackASN1ECDSASignature unpacks an ASN.1 encoded ECDSA signature into r and s values. This is typically used when working with crypto.Signer interfaces that return ASN.1 encoded signatures.

func UnpackECDSASignature

func UnpackECDSASignature(signature []byte, pubkey *ecdsa.PublicKey, r, s *big.Int) error

UnpackECDSASignature unpacks a JWS-format ECDSA signature into r and s values. The signature should be in the format specified by RFC 7515 (r||s as fixed-length byte arrays).

func Verify

func Verify(key any, alg string, payload, signature []byte) error

Verify verifies a digital signature using the specified key and algorithm.

This function loads the verifier registered in the dsig package _ONLY_. It does not support custom verifiers that the user might have registered.

func VerifyECDSA

func VerifyECDSA(key *ecdsa.PublicKey, payload, signature []byte, h crypto.Hash) error

VerifyECDSA verifies an ECDSA signature for the given payload. This function verifies the signature using the specified public key and hash algorithm. The payload parameter should be the pre-computed signing input (typically header.payload).

func VerifyECDSACryptoSigner

func VerifyECDSACryptoSigner(signer crypto.Signer, payload, signature []byte, h crypto.Hash) error

VerifyECDSACryptoSigner verifies an ECDSA signature for crypto.Signer implementations. This function is useful for verifying signatures created by hardware security modules or other implementations of the crypto.Signer interface. The payload parameter should be the pre-computed signing input (typically header.payload).

func VerifyEdDSA

func VerifyEdDSA(key ed25519.PublicKey, payload, signature []byte) error

VerifyEdDSA verifies an EdDSA (Ed25519) signature for the given payload. This function verifies the signature using Ed25519 verification algorithm. The payload parameter should be the pre-computed signing input (typically header.payload). EdDSA is deterministic and provides strong security guarantees without requiring hash function selection.

func VerifyHMAC

func VerifyHMAC(key, payload, signature []byte, hfunc func() hash.Hash) error

VerifyHMAC verifies an HMAC signature for the given payload. This function verifies the signature using the specified key and hash function. The payload parameter should be the pre-computed signing input (typically header.payload).

func VerifyRSA

func VerifyRSA(key *rsa.PublicKey, payload, signature []byte, h crypto.Hash, pss bool) error

VerifyRSA verifies an RSA signature for the given payload and header. This function constructs the signing input by encoding the header and payload according to JWS specification, then verifies the signature using the specified public key and hash algorithm. If pss is true, RSA-PSS verification is used; otherwise, PKCS#1 v1.5 verification is used.

Types

type AlgorithmInfo

type AlgorithmInfo struct {
	Family Family // The cryptographic family (HMAC, RSA, ECDSA, EdDSA)
	Meta   any    // Family-specific metadata
}

AlgorithmInfo contains metadata about a digital signature algorithm

func GetAlgorithmInfo

func GetAlgorithmInfo(name string) (AlgorithmInfo, bool)

GetAlgorithmInfo retrieves the algorithm information for a given algorithm name. Returns the info and true if found, zero value and false if not found.

type ECDSAFamilyMeta

type ECDSAFamilyMeta struct {
	Hash crypto.Hash // Hash algorithm
}

ECDSAFamilyMeta contains metadata specific to ECDSA algorithms

type EdDSAFamilyMeta

type EdDSAFamilyMeta struct {
}

EdDSAFamilyMeta contains metadata specific to EdDSA algorithms Currently EdDSA doesn't need specific metadata, but this provides extensibility

type Family

type Family int

Family represents the cryptographic algorithm family

const (
	InvalidFamily Family = iota
	HMAC
	RSA
	ECDSA
	EdDSAFamily
)

func (Family) String

func (f Family) String() string

String returns the string representation of the Family

type HMACFamilyMeta

type HMACFamilyMeta struct {
	HashFunc func() hash.Hash // Hash function constructor
}

HMACFamilyMeta contains metadata specific to HMAC algorithms

type RSAFamilyMeta

type RSAFamilyMeta struct {
	Hash crypto.Hash // Hash algorithm
	PSS  bool        // Whether to use PSS padding (false = PKCS#1 v1.5)
}

RSAFamilyMeta contains metadata specific to RSA algorithms

type VerificationError

type VerificationError struct {
	// contains filtered or unexported fields
}

VerificationError represents an error that occurred during signature verification.

func (*VerificationError) Error

func (e *VerificationError) Error() string

Directories

Path Synopsis
internal
ecutil
Package ecutil defines tools that help with elliptic curve related computation
Package ecutil defines tools that help with elliptic curve related computation

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL