9 71191436 2024-02-28 o "encoding/base64"
17 71191436 2024-02-28 o const requiredSigHeaders = "(request-target) host date digest"
19 71191436 2024-02-28 o // Sign signs the given HTTP request with the matching private key of the
20 71191436 2024-02-28 o // public key available at pubkeyURL.
21 71191436 2024-02-28 o func Sign(req *http.Request, key *rsa.PrivateKey, pubkeyURL string) error {
22 71191436 2024-02-28 o date := time.Now().UTC().Format(http.TimeFormat)
23 71191436 2024-02-28 o req.Header.Set("Date", date)
24 71191436 2024-02-28 o hash := sha256.New()
25 71191436 2024-02-28 o fmt.Fprintln(hash, "(request-target):", strings.ToLower(req.Method), req.URL.Path)
26 71191436 2024-02-28 o fmt.Fprintln(hash, "host:", req.URL.Hostname())
27 71191436 2024-02-28 o fmt.Fprintln(hash, "date:", date)
29 71191436 2024-02-28 o buf := &bytes.Buffer{}
30 71191436 2024-02-28 o io.Copy(buf, req.Body)
31 71191436 2024-02-28 o req.Body.Close()
32 71191436 2024-02-28 o req.Body = io.NopCloser(buf)
33 71191436 2024-02-28 o digest := sha256.Sum256(buf.Bytes())
34 71191436 2024-02-28 o d := "SHA-256=" + base64.StdEncoding.EncodeToString(digest[:])
35 71191436 2024-02-28 o fmt.Fprintf(hash, "digest: %s", d)
36 71191436 2024-02-28 o req.Header.Set("Digest", d)
38 71191436 2024-02-28 o sig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, hash.Sum(nil))
39 71191436 2024-02-28 o if err != nil {
42 71191436 2024-02-28 o bsig := base64.StdEncoding.EncodeToString(sig)
44 71191436 2024-02-28 o sigKeys := "(request-target) host date digest"
45 71191436 2024-02-28 o val := fmt.Sprintf("keyId=%q,algorithm=%q,headers=%q,signature=%q", pubkeyURL, "rsa-sha256", sigKeys, bsig)
46 71191436 2024-02-28 o req.Header.Set("Signature", val)
50 71191436 2024-02-28 o type signature struct {
52 71191436 2024-02-28 o algorithm string
54 71191436 2024-02-28 o signature string
57 71191436 2024-02-28 o func parseSignatureHeader(line string) (signature, error) {
58 71191436 2024-02-28 o var sig signature
59 71191436 2024-02-28 o for _, v := range strings.Split(line, ",") {
60 71191436 2024-02-28 o name, val, ok := strings.Cut(v, "=")
62 71191436 2024-02-28 o return sig, fmt.Errorf("bad field: %s from %s", v, line)
64 71191436 2024-02-28 o val = strings.Trim(val, `"`)
67 71191436 2024-02-28 o sig.keyID = val
68 71191436 2024-02-28 o case "algorithm":
69 71191436 2024-02-28 o sig.algorithm = val
70 71191436 2024-02-28 o case "headers":
71 71191436 2024-02-28 o sig.headers = val
72 71191436 2024-02-28 o case "signature":
73 71191436 2024-02-28 o sig.signature = val
75 71191436 2024-02-28 o return signature{}, fmt.Errorf("bad field name %s", name)
79 71191436 2024-02-28 o if sig.keyID == "" {
80 71191436 2024-02-28 o return sig, fmt.Errorf("missing signature field keyId")
81 71191436 2024-02-28 o } else if sig.algorithm == "" {
82 71191436 2024-02-28 o return sig, fmt.Errorf("missing signature field algorithm")
83 71191436 2024-02-28 o } else if sig.headers == "" {
84 71191436 2024-02-28 o return sig, fmt.Errorf("missing signature field headers")
85 71191436 2024-02-28 o } else if sig.signature == "" {
86 71191436 2024-02-28 o return sig, fmt.Errorf("missing signature field signature")
88 71191436 2024-02-28 o return sig, nil