package main import ( "crypto" "crypto/rand" "fmt" "net/http" "strings" "time" ) type Signer struct { key crypto.Signer keyID string } // Sign modifies the request, computing and setting the Signature header, and setting the Date header to the provided time. func (s Signer) Sign(r *http.Request, date time.Time) error { host := r.URL.Host path := r.URL.Path method := strings.ToLower(r.Method) stringToSign := fmt.Sprintf("(request-target): %s %s\nhost: %s\ndate: %s", method, path, host, date.Format(time.RFC1123)) sig, err := s.key.Sign(rand.Reader, []byte(stringToSign), nil) if err != nil { return err } r.Header.Set("Date", date.Format(time.RFC1123)) r.Header.Set("Signature", fmt.Sprintf(`keyId="%s",headers="(request-target) host date",signature="%s"`, s.keyID, sig)) return nil }