gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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.