httpsig

package module
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2019 License: BSD-3-Clause Imports: 20 Imported by: 2

README

httpsig

go get github.com/yukimochi/httpsig

Implementation of HTTP Signatures.

Supports many different combinations of MAC, HMAC signing of hash, or RSA signing of hash schemes. Its goals are:

  • Have a very simple interface for signing and validating
  • Support a variety of signing algorithms and combinations
  • Support setting either headers (Authorization or Signature)
  • Remaining flexible with headers included in the signing string
  • Support both HTTP requests and responses
  • Explicitly not support known-cryptographically weak algorithms

How to use

import "github.com/yukimochi/httpsig"

Signing

Signing a request or response requires creating a new Signer and using it:

func sign(privateKey crypto.PrivateKey, pubKeyId string, r *http.Request) error {
	prefs := []httpsig.Algorithm{httpsig.RSA_SHA512, httpsig.RSA_SHA256}
	// The "Date" and "Digest" headers must already be set on r, as well as r.URL.
	headersToSign := []string{httpsig.RequestTarget, "date", "digest"}
	signer, chosenAlgo, err := httpsig.NewSigner(prefs, headersToSign, httpsig.Signature)
	if err != nil {
		return err
	}
	// If r were a http.ResponseWriter, call SignResponse instead.
	return signer.SignRequest(privateKey, pubKeyId, r)
}

Signers are not safe for concurrent use by goroutines, so be sure to guard access:

type server struct {
	signer httpsig.Signer
	mu *sync.Mutex
}

func (s *server) handlerFunc(w http.ResponseWriter, r *http.Request) {
	privateKey := ...
	pubKeyId := ...
	// Set headers and such on w
	s.mu.Lock()
	defer s.mu.Unlock()
	err := s.signer.SignResponse(privateKey, pubKeyId, w)
	if err != nil {
		...
	}
	...
}

The pubKeyId will be used at verification time.

Verifying

Verifying requires an application to use the pubKeyId to both retrieve the key needed for verification as well as determine the algorithm to use. Use a Verifier:

func verify(r *http.Request) error {
	verifier, err := httpsig.NewVerifier(r)
	if err != nil {
		return err
	}
	pubKeyId := verifier.KeyId()
	var algo httpsig.Algorithm = ...
	var pubKey crypto.PublicKey = ...
	return verifier.Verify(pubKey, algo)
}

Verifiers are not safe for concurrent use by goroutines, but since they are constructed on a per-request or per-response basis it should not be a common restriction.

Documentation

Overview

Implements HTTP request and response signing and verification. Supports the major MAC and asymmetric key signature algorithms. It has several safety restrictions: One, none of the widely known non-cryptographically safe algorithms are permitted; Two, the RSA SHA256 algorithms must be available in the binary (and it should, barring export restrictions); Finally, the library assumes either the 'Authorizationn' or 'Signature' headers are to be set (but not both).

Index

Constants

View Source
const (

	// RequestTarget specifies to include the http request method and
	// entire URI in the signature. Pass it as a header to NewSigner.
	RequestTarget = "(request-target)"
)

Variables

This section is empty.

Functions

func NewSigner

func NewSigner(prefs []Algorithm, headers []string, scheme SignatureScheme) (Signer, Algorithm, error)

NewSigner creates a new Signer with the provided algorithm preferences to make HTTP signatures. Only the first available algorithm will be used, which is returned by this function along with the Signer. If none of the preferred algorithms were available, then the default algorithm is used. The headers specified will be included into the HTTP signatures.

The provided scheme determines which header is populated with the HTTP Signature.

An error is returned if an unknown or a known cryptographically insecure Algorithm is provided.

Types

type Algorithm

type Algorithm string

Algorithm specifies a cryptography secure algorithm for signing HTTP requests and responses.

const (
	// MAC-based algoirthms.
	HMAC_SHA224      Algorithm = hmacPrefix + "-" + sha224String
	HMAC_SHA256      Algorithm = hmacPrefix + "-" + sha256String
	HMAC_SHA384      Algorithm = hmacPrefix + "-" + sha384String
	HMAC_SHA512      Algorithm = hmacPrefix + "-" + sha512String
	HMAC_RIPEMD160   Algorithm = hmacPrefix + "-" + ripemd160String
	HMAC_SHA3_224    Algorithm = hmacPrefix + "-" + sha3_224String
	HMAC_SHA3_256    Algorithm = hmacPrefix + "-" + sha3_256String
	HMAC_SHA3_384    Algorithm = hmacPrefix + "-" + sha3_384String
	HMAC_SHA3_512    Algorithm = hmacPrefix + "-" + sha3_512String
	HMAC_SHA512_224  Algorithm = hmacPrefix + "-" + sha512_224String
	HMAC_SHA512_256  Algorithm = hmacPrefix + "-" + sha512_256String
	HMAC_BLAKE2S_256 Algorithm = hmacPrefix + "-" + blake2s_256String
	HMAC_BLAKE2B_256 Algorithm = hmacPrefix + "-" + blake2b_256String
	HMAC_BLAKE2B_384 Algorithm = hmacPrefix + "-" + blake2b_384String
	HMAC_BLAKE2B_512 Algorithm = hmacPrefix + "-" + blake2b_512String
	BLAKE2S_256      Algorithm = blake2s_256String
	BLAKE2B_256      Algorithm = blake2b_256String
	BLAKE2B_384      Algorithm = blake2b_384String
	BLAKE2B_512      Algorithm = blake2b_512String
	// RSA-based algorithms.
	RSA_SHA224 Algorithm = rsaPrefix + "-" + sha224String
	// RSA_SHA256 is the default algorithm.
	RSA_SHA256    Algorithm = rsaPrefix + "-" + sha256String
	RSA_SHA384    Algorithm = rsaPrefix + "-" + sha384String
	RSA_SHA512    Algorithm = rsaPrefix + "-" + sha512String
	RSA_RIPEMD160 Algorithm = rsaPrefix + "-" + ripemd160String
)

type SignatureScheme

type SignatureScheme string

HTTP Signatures can be applied to different HTTP headers, depending on the expected application behavior.

const (
	// Signature will place the HTTP Signature into the 'Signature' HTTP
	// header.
	Signature SignatureScheme = "Signature"
	// Authorization will place the HTTP Signature into the 'Authorization'
	// HTTP header.
	Authorization SignatureScheme = "Authorization"
)

type Signer

type Signer interface {
	// SignRequest signs the request using a private key. The public key id
	// is used by the HTTP server to identify which key to use to verify the
	// signature.
	//
	// If the Signer was created using a MAC based algorithm, then the key
	// is expected to be of type []byte. If the Signer was created using an
	// RSA based algorithm, then the private key is expected to be of type
	// *rsa.PrivateKey.
	SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *http.Request) error
	// SignResponse signs the response using a private key. The public key
	// id is used by the HTTP client to identify which key to use to verify
	// the signature.
	//
	// If the Signer was created using a MAC based algorithm, then the key
	// is expected to be of type []byte. If the Signer was created using an
	// RSA based algorithm, then the private key is expected to be of type
	// *rsa.PrivateKey.
	SignResponse(pKey crypto.PrivateKey, pubKeyId string, r http.ResponseWriter) error
}

Signers will sign HTTP requests or responses based on the algorithms and headers selected at creation time.

Signers are not safe to use between multiple goroutines.

Note that signatures do set the deprecated 'algorithm' parameter for backwards compatibility.

type Verifier

type Verifier interface {
	// KeyId gets the public key id that the signature is signed with.
	//
	// Note that the application is expected to determine the algorithm
	// used based on metadata or out-of-band information for this key id.
	KeyId() string
	// Verify accepts the public key specified by KeyId and returns an
	// error if verification fails or if the signature is malformed. The
	// algorithm must be the one used to create the signature in order to
	// pass verification. The algorithm is determined based on metadata or
	// out-of-band information for the key id.
	//
	// If the signature was created using a MAC based algorithm, then the
	// key is expected to be of type []byte. If the signature was created
	// using an RSA based algorithm, then the public key is expected to be
	// of type *rsa.PublicKey.
	Verify(pKey crypto.PublicKey, algo Algorithm) error
}

Verifier verifies HTTP Signatures.

It will determine which of the supported headers has the parameters that define the signature.

Verifiers are not safe to use between multiple goroutines.

Note that verification ignores the deprecated 'algorithm' parameter.

func NewResponseVerifier

func NewResponseVerifier(r *http.Response) (Verifier, error)

NewResponseVerifier verifies the given response. It returns errors under the same conditions as NewVerifier.

func NewVerifier

func NewVerifier(r *http.Request) (Verifier, error)

NewVerifier verifies the given request. It returns an error if the HTTP Signature parameters are not present in any headers, are present in more than one header, are malformed, or are missing required parameters. It ignores unknown HTTP Signature parameters.

Jump to

Keyboard shortcuts

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