README.md (2892B)
1 # httpsig 2 3 `go get github.com/go-fed/httpsig` 4 5 Implementation of [HTTP Signatures](https://tools.ietf.org/html/draft-cavage-http-signatures). 6 7 Supports many different combinations of MAC, HMAC signing of hash, or RSA 8 signing of hash schemes. Its goals are: 9 10 * Have a very simple interface for signing and validating 11 * Support a variety of signing algorithms and combinations 12 * Support setting either headers (`Authorization` or `Signature`) 13 * Remaining flexible with headers included in the signing string 14 * Support both HTTP requests and responses 15 * Explicitly not support known-cryptographically weak algorithms 16 * Support automatic signing and validating Digest headers 17 18 ## How to use 19 20 `import "github.com/go-fed/httpsig"` 21 22 ### Signing 23 24 Signing a request or response requires creating a new `Signer` and using it: 25 26 ``` 27 func sign(privateKey crypto.PrivateKey, pubKeyId string, r *http.Request) error { 28 prefs := []httpsig.Algorithm{httpsig.RSA_SHA512, httpsig.RSA_SHA256} 29 digestAlgorithm := DigestSha256 30 // The "Date" and "Digest" headers must already be set on r, as well as r.URL. 31 headersToSign := []string{httpsig.RequestTarget, "date", "digest"} 32 signer, chosenAlgo, err := httpsig.NewSigner(prefs, digestAlgorithm, headersToSign, httpsig.Signature) 33 if err != nil { 34 return err 35 } 36 // To sign the digest, we need to give the signer a copy of the body... 37 // ...but it is optional, no digest will be signed if given "nil" 38 body := ... 39 // If r were a http.ResponseWriter, call SignResponse instead. 40 return signer.SignRequest(privateKey, pubKeyId, r, body) 41 } 42 ``` 43 44 `Signer`s are not safe for concurrent use by goroutines, so be sure to guard 45 access: 46 47 ``` 48 type server struct { 49 signer httpsig.Signer 50 mu *sync.Mutex 51 } 52 53 func (s *server) handlerFunc(w http.ResponseWriter, r *http.Request) { 54 privateKey := ... 55 pubKeyId := ... 56 // Set headers and such on w 57 s.mu.Lock() 58 defer s.mu.Unlock() 59 // To sign the digest, we need to give the signer a copy of the response body... 60 // ...but it is optional, no digest will be signed if given "nil" 61 body := ... 62 err := s.signer.SignResponse(privateKey, pubKeyId, w, body) 63 if err != nil { 64 ... 65 } 66 ... 67 } 68 ``` 69 70 The `pubKeyId` will be used at verification time. 71 72 ### Verifying 73 74 Verifying requires an application to use the `pubKeyId` to both retrieve the key 75 needed for verification as well as determine the algorithm to use. Use a 76 `Verifier`: 77 78 ``` 79 func verify(r *http.Request) error { 80 verifier, err := httpsig.NewVerifier(r) 81 if err != nil { 82 return err 83 } 84 pubKeyId := verifier.KeyId() 85 var algo httpsig.Algorithm = ... 86 var pubKey crypto.PublicKey = ... 87 // The verifier will verify the Digest in addition to the HTTP signature 88 return verifier.Verify(pubKey, algo) 89 } 90 ``` 91 92 `Verifier`s are not safe for concurrent use by goroutines, but since they are 93 constructed on a per-request or per-response basis it should not be a common 94 restriction.