ファイルへ移動
Cory Slep d685ff0472 improve digest test and run go fmt 2019-09-05 00:01:36 +02:00
LICENSE HTTP Signature signing in golang. 2018-05-15 23:03:43 +02:00
README.md Fix wording in comment 2018-05-16 23:22:30 +02:00
algorithms.go Add IsSupportedHttpSigAlgorithm 2019-09-03 19:40:51 +02:00
algorithms_test.go Fix vet lint 2018-05-30 21:11:34 +02:00
digest.go Add functions for handling Digest headers. 2019-09-04 23:35:07 +02:00
digest_test.go improve digest test and run go fmt 2019-09-05 00:01:36 +02:00
go.mod Add go.mod file for vgo 2018-05-30 19:51:16 +02:00
go.modverify Add go.modverify for vgo 2018-05-30 21:03:05 +02:00
httpsig.go Add test condition for auth-scheme, fix bug in HMAC 2019-03-09 23:56:49 +01:00
httpsig_test.go Add appendix C tests 2019-03-10 08:56:13 +00:00
signing.go Add appendix C tests 2019-03-10 08:56:13 +00:00
verifying.go Add "Signature" for "auth-scheme" 2019-02-28 22:38:53 +01:00

README.md

httpsig

go get github.com/go-fed/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/go-fed/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.