httpsign

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Nov 15, 2024 License: MIT Imports: 9 Imported by: 0

README

httpsign

CI Go Reference

httpsign provides utilities for creating, encoding, and verifying signatures within HTTP requests. Library provides both the transport to create digital signatures or message authentication codes (MACs), and a middleware to verify such signatures.

Overview

The library provides the following signature algorithms:

The API is based on four interfaces: Signer, Verifier and SignerSource, VerifierSource.

Signer is essentially a wrapper around the signature algorithm's private key. Because the private key also contains the corresponding public key, Signer can be used for verification as well. SignerSource abstracts the retrieval of Signer based on the provided key ID.

Verifier uses the public key for verification. It is useful in situations where the user only has access to the public key and not the private key. VerifierSource abstracts the retrieval of Verifier based on the provided key ID.

The HMAC algorithm is an exception, as it uses the same shared secret key for both signing and verification. Therefore, the API provides a single structure, HMAC, for both signing and verification.

Usage

Here is an example using HMAC-SHA-256 algorithm:

type staticSource struct{ h *hmac.HMAC }

func (s staticSource) Signer(ctx context.Context, kid string) (Signer, error) {
	return s.h, nil
}
func (s staticSource) Verifier(ctx context.Context, kid string) (Verifier, error) {
	return s.h, nil
}

const (
	secret = "shared-secret"
	kid    = "key-id"
)

// Create the signer using the shared secret key.
sgn, err := hmac.New([]byte(secret), crypto.SHA256)
if err != nil {
	log.Fatal(err)
}

// Create the source given the signer.
src := staticSource{sgn}

// Create the Transport.
tr := NewTransport(src, kid)

// Create an HTTP client using our transport to sign outgoing requests.
c := &http.Client{Transport: tr}

// Create the Middleware to verify incoming requests signatures.
m := Middleware(src, DefaultErrorHandler)

// Wrap the handler.
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello")
})
handler = m(handler)

http.Handle("/api/foo", handler)

Here is an example using RSASSA-PKCS1-v1.5 SHA-256 algorithm:

type staticSource struct{ h *rsa.PKCSSigner }

func (s staticSource) Signer(ctx context.Context, kid string) (Signer, error) {
	return s.h, nil
}
func (s staticSource) Verifier(ctx context.Context, kid string) (Verifier, error) {
	return s.h, nil
}

const kid = "key-id"

privateKey, err := stdrsa.GenerateKey(rand.Reader, 2048)
hash := crypto.SHA256

// Create the signer using the shared secret key.
sgn, err := rsa.NewPKCSSigner(privateKey, hash)
if err != nil {
	log.Fatal(err)
}

// Create the source given the signer.
src := staticSource{sgn}

// Create the Transport.
tr := NewTransport(src, kid)

// Create an HTTP client using our transport to sign outgoing requests.
c := &http.Client{Transport: tr}

// Create the Middleware to verify incoming requests signatures.
m := Middleware(src, DefaultErrorHandler)

// Alternatively, we can explicitly create a Verifier using the public key.
vrf, err := hsrsa.NewPKCSVerifier(&privateKey.PublicKey, hash)
if err != nil {
	log.Fatal(err)
}

// Wrap the handler.
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello")
})
handler = m(handler)

http.Handle("/api/foo", handler)

Documentation

Overview

Package httpsign provides utilities for signing and verifying HTTP requests.

Index

Constants

View Source
const (
	SignatureHeader = "X-Signature"
	TimestampHeader = "X-Signature-Timestamp"
	KidHeader       = "X-Key-ID"
)

Variables

View Source
var (
	// ErrRequestVerification represents a failure to verify an HTTP request.
	ErrRequestVerification = errors.New("failed to verify HTTP request")
)

Functions

func DefaultErrorHandler

func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error)

DefaultErrorHandler handles errors as follows:

  • If the error is ErrRequestVerification, it sends a 401 Unauthorized response.
  • For any other errors, it defaults to sending a 500 Internal Server Error response.

func Middleware

func Middleware(
	source VerifierSource,
	errHandler func(w http.ResponseWriter, r *http.Request, err error),
) func(http.Handler) http.Handler

Middleware creates middleware that verifies HTTP request signatures using a Verifier from the provided source and handles errors with a custom handler.

func Sign added in v0.2.0

func Sign(s Signer, timestamp time.Time, r *http.Request) error

Sign signs the HTTP request using the provided signer and timestamp.

func Verify added in v0.2.0

func Verify(v Verifier, r *http.Request) error

Verify verifies the HTTP request using the provided verifier.

Types

type Signer

type Signer interface {
	Sign(message []byte) ([]byte, error)
}

Signer signs messages. It must be safe for concurrent use by multiple goroutines.

type SignerSource added in v0.2.0

type SignerSource interface {
	Signer(ctx context.Context, kid string) (Signer, error)
}

SignerSource provides a Signer given a key ID. It must be safe for concurrent use by multiple goroutines.

type Transport

type Transport struct {
	// Base is the base http.RoundTripper used to make HTTP requests.
	// By default, http.DefaultTransport is used.
	Base http.RoundTripper
	// contains filtered or unexported fields
}

Transport is an http.RoundTripper which signs outgoing HTTP requests.

func NewTransport

func NewTransport(source SignerSource, kid string) *Transport

NewTransport returns a new Transport using a SignerSource with the provided key ID.

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip signs the request.

type Verifier

type Verifier interface {
	Verify(message []byte, signature []byte) (bool, error)
}

Verifier verifies message signatures. It must be safe for concurrent use by multiple goroutines.

type VerifierSource added in v0.2.0

type VerifierSource interface {
	Verifier(ctx context.Context, kid string) (Verifier, error)
}

VerifierSource provides a Verifier given a key ID. It must be safe for concurrent use by multiple goroutines.

Directories

Path Synopsis
Package ecdsa provides utilities for signing and verifying messages using ECDSA.
Package ecdsa provides utilities for signing and verifying messages using ECDSA.
Package ed25519 provides utilities for signing and verifying messages using Ed25519.
Package ed25519 provides utilities for signing and verifying messages using Ed25519.
Package hmac provides utilities for signing and verifying messages using HMAC.
Package hmac provides utilities for signing and verifying messages using HMAC.
Package rsa provides utilities for signing and verifying messages using RSA.
Package rsa provides utilities for signing and verifying messages using RSA.

Jump to

Keyboard shortcuts

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