Documentation
¶
Index ¶
- Variables
- func NoRFC9421(h *Transport) error
- type KeyEncoding
- type OptionFn
- func WithActor(act *vocab.Actor, prv crypto.PrivateKey) OptionFn
- func WithAlg(alg KeyEncoding) OptionFn
- func WithApplicationTag(t string) OptionFn
- func WithCoveredComponents(comp ...string) OptionFn
- func WithLogger(l lw.Logger) OptionFn
- func WithNonce(nonceFn func() (string, error)) OptionFn
- func WithTransport(tr http.RoundTripper) OptionFn
- type Transport
Examples ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ( // HeadersToSign is the list of headers that will be used to generate the // Draft version of HTTP-Signature // // In regular builds, this list contains the "Date" header which makes it // compatible with the wider fediverse, at the expense of debuggability. HeadersToSign = []string{httpsig.RequestTarget, "host", "date"} // FetchCoveredComponents is the list of components to be used for generating the // RFC9421 Signature Base for GET and HEAD requests. // https://www.rfc-editor.org/rfc/rfc9421.html#name-derived-components FetchCoveredComponents = []string{"@method", "@target-uri", "date"} // AdditionalPostCoveredComponents is the list of components to be used for generating the // RFC9421 Signature Base for POST, PUT, DELETE requests. AdditionalPostCoveredComponents = []string{"content-type"} )
View Source
var ErrRetry = errors.Newf("retry")
Functions ¶
Types ¶
type KeyEncoding ¶
type KeyEncoding int
const ( KeyTypeUnknown KeyEncoding = 0 KeyTypePKCS KeyEncoding = 1 KeyTypePSS KeyEncoding = 2 )
type OptionFn ¶
func WithAlg ¶
func WithAlg(alg KeyEncoding) OptionFn
func WithApplicationTag ¶
func WithCoveredComponents ¶
func WithLogger ¶
func WithTransport ¶
func WithTransport(tr http.RoundTripper) OptionFn
type Transport ¶
type Transport struct {
Base http.RoundTripper
Alg KeyEncoding
Key crypto.PrivateKey
Actor *vocab.Actor
// contains filtered or unexported fields
}
func New ¶
New initializes the Transport TODO(marius): we need to add to the return values the errors that might come from the initialization functions.
func (*Transport) RoundTrip ¶
RoundTrip dispatches the received request after signing it. We currently use the double knocking mechanism Mastodon popularized: * we first attempt to sign the request with RFC9421 compliant signature, * if it failed, we try again using a Cavage draft 8 version signature. Additionally, if everything failed, and we're operating with a fetch request, we make one last, non-signed attempt.
Example (Draft) ¶
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%s\n", r.Header.Get("Signature"))
w.WriteHeader(http.StatusOK)
}))
defer srv.Close()
tr := New(WithTransport(http.DefaultTransport), WithActor(jdoeActor, prv), NoRFC9421)
// The below functionality would be equivalent to the following usage:
//http.DefaultClient.Transport = tr
//res, err := http.Get(srv.URL)
req := httptest.NewRequest(http.MethodGet, srv.URL, nil)
host := strings.TrimPrefix(srv.URL, "http://")
host = host[:strings.Index(host, ":")]
req.Header.Set("Host", host)
req.Header.Set("Date", millenium.Format(http.TimeFormat))
_, _ = tr.RoundTrip(req)
Output: keyId="https://example.com/~johndoe#main",algorithm="hs2019",headers="(request-target) host",signature="RhsET77hrToaCyh/2++dFw0PGn64AoZBR3X2r+rVFWDT1CtobC1sVwXcc91v2c2HmB3A6P3EH1truRnhbNpL2sOgmqUbkRGBoO5afsgaRzRg/z8BwKDlnP9w/6zYlvoYH2VcgQpCTKPUkYDGUexFQDxBJMFime+d361I3ptO/Jc="
Example (Rfc9421) ¶
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
verifier, _ := httpsig.NewVerifier(
mockKeyResolver{},
httpsig.WithNonceChecker(mockNonceChecker(true)),
httpsig.WithValidateAllSignatures(),
httpsig.WithValidityTolerance(time.Hour),
httpsig.WithMaxAge(time.Hour),
)
err := verifier.Verify(httpsig.MessageFromRequest(r))
if err != nil {
fmt.Printf("Verification failed: %s\n", err)
} else {
fmt.Printf("Verification succeeded\n")
}
w.WriteHeader(http.StatusOK)
}))
defer srv.Close()
tr := New(WithTransport(http.DefaultTransport), WithActor(&exActorRSA, prvKeyRSA), WithAlg(KeyTypePKCS), WithNonce(sameNonce))
req := httptest.NewRequest(http.MethodPost, srv.URL, strings.NewReader(`{"hello": "world"}`))
req.Header.Set("Host", "example.com")
req.Header.Set("Date", millenium.Format(http.TimeFormat))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Content-Length", "18")
_, _ = tr.RoundTrip(req)
Output: Verification succeeded
Click to show internal directories.
Click to hide internal directories.