httpsignature

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 34 Imported by: 0

README

http-signature

CI CodeQL Coverage Mutation Documentation Go Reference Release Go License

http-signature implements HTTP Message Signatures (RFC 9421) and HTTP digest fields (RFC 9530) for Go net/http messages. The core separates Structured Fields syntax, signature-base construction, cryptographic algorithms, signing and verification policy, key resolution, replay consumption, and HTTP adapters.

It does not replace TLS, authentication, authorization, or capabilities. A successful verification proves only cryptographic validity and conformance to the selected application profile.

Install

go get github.com/faustbrian/go-http-signature@v1

Minimal request signing

profile, _ := httpsignature.NewSigningProfile(httpsignature.SigningProfileConfig{
    AllowedAlgorithms: []httpsignature.Algorithm{httpsignature.HMACSHA256},
    CoveredComponents: []httpsignature.ComponentIdentifier{
        {Name: "@method"},
        {Name: "@authority"},
        {Name: "content-digest"},
    },
    Expires: httpsignature.ParameterRequired,
    AlgorithmParameter: httpsignature.ParameterRequired,
    Nonce: httpsignature.ParameterForbidden,
    Tag: httpsignature.ParameterForbidden,
    Lifetime: time.Minute,
    ResolveTimeout: time.Second,
    Now: time.Now,
    Provider: provider,
})

signing, _ := httpsignature.NewSigningRoundTripper(httpsignature.SigningRoundTripperConfig{
    Transport: http.DefaultTransport,
    Signer: httpsignature.NewSigner(profile),
    Label: "sig",
    Existing: httpsignature.ExistingSignaturesReject,
    Options: func(context.Context, *http.Request) (httpsignature.SigningOptions, error) {
        return httpsignature.SigningOptions{}, nil
    },
})

digesting, _ := httpsignature.NewBufferedContentDigestRoundTripper(
    httpsignature.BufferedContentDigestRoundTripperConfig{
        Transport: signing,
        Algorithms: []httpsignature.DigestAlgorithm{httpsignature.SHA256},
        MaxBytes: 1 << 20,
    },
)
client := &http.Client{Transport: digesting}

The wrapper order is significant: digest first, signature second, network transport last. This ensures the signed message already contains the digest.

Verification model

Create a VerificationProfile with explicit allowed algorithms, required components, time policy, nonce policy, key resolver, resolution timeout, and optional mandatory external request context. Applications select the signature label and map typed failures to HTTP responses. Verification metadata stored in context is not an authorization decision.

Behind a proxy, set RequireExternalRequestContext and supply a trusted ExternalRequestContext from deployment configuration. The package never reads Forwarded or X-Forwarded-* automatically.

Bodies and trailers

  • BufferedContentDigestRoundTripper consumes and closes the outbound caller body, delegates a cloned replayable body, and enforces MaxBytes.
  • BufferedContentDigestVerificationMiddleware reads and verifies before application code sees the body.
  • TrailerSigningRoundTripper hashes while the transport reads and emits a signed Content-Digest trailer at EOF. Declared application trailer values populated at EOF are preserved; early responses and trailer-name changes fail closed. It is one-attempt and deliberately clears GetBody; retry policy must create a fresh request.
  • BufferedTrailerVerificationMiddleware waits for EOF before trusting or releasing content, because trailers can be absent or dropped.
  • TrailerResponseSigningMiddleware streams response bytes, declares digest and signature trailers before the final header, and reports any failure that occurs after bytes were emitted.
  • BufferedTrailerVerifyingRoundTripper waits for response EOF, verifies the authenticated digest trailers, and only then returns a replayable body.
  • ResponseSigningMiddleware buffers under an explicit limit and can compute and cover Content-Digest. Its required ReportError callback records redacted output failures after signed headers commit. Use the response trailer adapter for ordinary streaming and flushing. Both response integrations reject hijacking, full duplex, protocol switching, and successful CONNECT because subsequent bytes are not HTTP content. Buffered 205 responses reject handler body writes and sign empty content; the trailer adapter rejects 205 because that status cannot carry its mandatory trailers.

Digest bytes are the HTTP content as presented at the adapter boundary. Place compression before or after digesting according to whether the digest must cover coded or uncoded bytes; RFC 9530 Content-Digest covers actual message content, including applied content coding. Repr-Digest requires the application to supply the selected representation bytes when they differ from message content.

Supported algorithms

All active IANA RFC 9421 algorithms are implemented with strict key binding: RSA-PSS-SHA-512, RSA-v1.5-SHA-256, HMAC-SHA-256, ECDSA P-256/SHA-256, ECDSA P-384/SHA-384, and Ed25519. RSA keys require 2048–8192 bits and RSA signatures are limited to 1024 bytes; HMAC keys require 32–64 bytes. RSA-PSS and ECDSA use Go-managed cryptographically secure randomness. SigningProfileConfig.Random and the final reader argument to Sign are retained for source compatibility and ignored. RFC 9530 computation supports only active SHA-256 and SHA-512. Deprecated digest algorithms remain parseable for negotiation but are never computed or accepted as required algorithms.

Signature-base construction defaults to a 1 MiB output ceiling. Set MessageContext.MaxSignatureBaseBytes to a smaller positive limit at trust boundaries that permit less header or target data.

Signature bases use net/http transport-owned Host, content-length, transfer encoding, trailer, and connection state rather than stale header-map aliases. When a response signature covers one of those fields, set MessageContext.ResponseTransport to ResponseTransportReceived for a response parsed by net/http or returned by a RoundTripper, or to ResponseTransportWrite for the output modeled by Response.Write. The zero value accepts only field identity that is identical under both models and otherwise fails closed. Set an explicit ASCII User-Agent or Host before covering it. Inbound Trailer declaration order is unavailable in net/http and therefore fails closed; cover actual trailer fields with tr. Cookie coverage requires one canonical field value, and multiple Set-Cookie lines require bs.

Legacy and vendor protocols

The compatibility package provides explicitly named RoundTripper and verification-middleware boundaries for Cavage draft signatures, AWS Signature V4, OAuth 1.0, and named vendor schemes. Applications must supply the actual protocol implementation; the boundary clones outbound request metadata, preserves body ownership, sanitizes callback failures, and never invokes or extends the RFC 9421 parsers. Outbound callbacks can emit non-RFC-signature vendor fields, but cannot change request identity or RFC 9421 signature fields. Inbound callbacks operate on an isolated read-only view; none of their request mutations reach later RFC verification. Do not install a compatibility adapter and an RFC 9421 adapter as interchangeable authentication paths.

Documentation

License

MIT. See LICENSE and NOTICE.

Ecosystem

Use the Golib documentation portal to choose companion packages, supported stacks, recipes, and operations guidance.

Documentation

Overview

Package httpsignature implements HTTP Message Signatures and digest fields.

Package httpsignature implements RFC 9421 HTTP Message Signatures and RFC 9530 digest fields for net/http.

Parsing and cryptographic validity do not authenticate or authorize an operation by themselves. Applications must construct explicit signing and verification profiles, resolve algorithm-bound keys, enforce replay policy, supply trusted external request context behind proxies, and map safe typed failures to their own protocol.

Example (ClientAndServerMiddleware)
package main

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"time"

	httpsignature "github.com/faustbrian/go-http-signature"
)

type exampleProvider struct {
	key httpsignature.SigningKey
}

func (provider exampleProvider) SigningKey(context.Context) (httpsignature.SigningKey, error) {
	return provider.key, nil
}

type exampleResolver struct {
	key httpsignature.ResolvedKey
}

func (resolver exampleResolver) Resolve(context.Context, string) (httpsignature.ResolvedKey, error) {
	return resolver.key, nil
}

func main() {
	now := time.Unix(1_700_000_000, 0)
	key, _ := httpsignature.NewHMACKey([]byte("0123456789abcdef0123456789abcdef"))
	components := []httpsignature.ComponentIdentifier{
		{Name: "@method"}, {Name: "@authority"}, {Name: "content-digest"},
	}
	signingProfile, _ := httpsignature.NewSigningProfile(httpsignature.SigningProfileConfig{
		AllowedAlgorithms: []httpsignature.Algorithm{httpsignature.HMACSHA256}, CoveredComponents: components,
		Expires: httpsignature.ParameterForbidden, AlgorithmParameter: httpsignature.ParameterRequired,
		Nonce: httpsignature.ParameterForbidden, Tag: httpsignature.ParameterForbidden,
		ResolveTimeout: time.Second, Now: func() time.Time { return now },
		Provider: exampleProvider{key: httpsignature.SigningKey{
			KeyID: "key-2026", Algorithm: httpsignature.HMACSHA256, Key: key,
			NotBefore: now.Add(-time.Hour), NotAfter: now.Add(time.Hour),
		}},
	})
	verificationProfile, _ := httpsignature.NewVerificationProfile(httpsignature.VerificationProfileConfig{
		AllowedAlgorithms: []httpsignature.Algorithm{httpsignature.HMACSHA256}, RequiredComponents: components,
		Created: httpsignature.ParameterRequired, Expires: httpsignature.ParameterForbidden,
		AlgorithmParameter: httpsignature.ParameterRequired, Nonce: httpsignature.ParameterForbidden,
		Tag: httpsignature.ParameterForbidden, MaxAge: time.Minute, ClockSkew: time.Second,
		ResolveTimeout: time.Second, Now: func() time.Time { return now },
		Resolver: exampleResolver{key: httpsignature.ResolvedKey{
			Algorithm: httpsignature.HMACSHA256, Key: key,
			NotBefore: now.Add(-time.Hour), NotAfter: now.Add(time.Hour), FreshUntil: now.Add(time.Minute),
		}},
	})

	mapError := func(writer http.ResponseWriter, _ *http.Request, _ error) {
		http.Error(writer, "invalid signed request", http.StatusUnauthorized)
	}
	verifySignature, _ := httpsignature.NewRequestVerificationMiddleware(
		httpsignature.RequestVerificationMiddlewareConfig{
			Verifier: httpsignature.NewVerifier(verificationProfile),
			SelectLabel: func(*http.Request, httpsignature.SignatureInputs, httpsignature.Signatures) (string, error) {
				return "sig", nil
			},
			MapError: mapError,
		},
	)
	verifyDigest, _ := httpsignature.NewBufferedContentDigestVerificationMiddleware(
		httpsignature.BufferedContentDigestVerificationMiddlewareConfig{
			RequiredAlgorithms: []httpsignature.DigestAlgorithm{httpsignature.SHA256},
			MaxBytes:           1024, MapError: mapError,
		},
	)
	server := httptest.NewServer(verifyDigest(verifySignature(http.HandlerFunc(
		func(writer http.ResponseWriter, request *http.Request) {
			body, _ := io.ReadAll(request.Body)
			_, verified := httpsignature.VerifiedSignatureFromContext(request.Context())
			_, _ = fmt.Fprintln(writer, verified, string(body))
		},
	))))
	defer server.Close()

	signingTransport, _ := httpsignature.NewSigningRoundTripper(httpsignature.SigningRoundTripperConfig{
		Transport: server.Client().Transport, Signer: httpsignature.NewSigner(signingProfile), Label: "sig",
		Existing: httpsignature.ExistingSignaturesReject,
		Options: func(context.Context, *http.Request) (httpsignature.SigningOptions, error) {
			return httpsignature.SigningOptions{}, nil
		},
	})
	digestTransport, _ := httpsignature.NewBufferedContentDigestRoundTripper(
		httpsignature.BufferedContentDigestRoundTripperConfig{
			Transport: signingTransport, Algorithms: []httpsignature.DigestAlgorithm{httpsignature.SHA256}, MaxBytes: 1024,
		},
	)
	client := &http.Client{Transport: digestTransport}
	response, _ := client.Post(server.URL+"/messages", "text/plain", strings.NewReader("signed payload"))
	responseBody, _ := io.ReadAll(response.Body)
	_ = response.Body.Close()
	fmt.Print(response.StatusCode, " ", string(responseBody))
}
Output:
200 true signed payload
Example (RequestSignAndVerify)
package main

import (
	"context"
	"fmt"
	"net/http"
	"time"

	httpsignature "github.com/faustbrian/go-http-signature"
)

type exampleProvider struct {
	key httpsignature.SigningKey
}

func (provider exampleProvider) SigningKey(context.Context) (httpsignature.SigningKey, error) {
	return provider.key, nil
}

type exampleResolver struct {
	key httpsignature.ResolvedKey
}

func (resolver exampleResolver) Resolve(context.Context, string) (httpsignature.ResolvedKey, error) {
	return resolver.key, nil
}

func main() {
	now := time.Unix(1_700_000_000, 0)
	key, _ := httpsignature.NewHMACKey([]byte("0123456789abcdef0123456789abcdef"))
	signingProfile, _ := httpsignature.NewSigningProfile(httpsignature.SigningProfileConfig{
		AllowedAlgorithms:  []httpsignature.Algorithm{httpsignature.HMACSHA256},
		CoveredComponents:  []httpsignature.ComponentIdentifier{{Name: "@method"}, {Name: "@authority"}},
		Expires:            httpsignature.ParameterForbidden,
		AlgorithmParameter: httpsignature.ParameterRequired,
		Nonce:              httpsignature.ParameterForbidden,
		Tag:                httpsignature.ParameterForbidden,
		ResolveTimeout:     time.Second,
		Now:                func() time.Time { return now },
		Provider: exampleProvider{key: httpsignature.SigningKey{
			KeyID: "key-2026", Algorithm: httpsignature.HMACSHA256, Key: key,
			NotBefore: now.Add(-time.Hour), NotAfter: now.Add(time.Hour),
		}},
	})
	request, _ := http.NewRequest(http.MethodPost, "https://api.example/pay", nil)
	signed, _ := httpsignature.NewSigner(signingProfile).Sign(
		context.Background(), httpsignature.MessageContext{Request: request}, "sig", httpsignature.SigningOptions{},
	)

	inputs, _ := httpsignature.ParseSignatureInputs([]string{signed.SignatureInputField()})
	signatures, _ := httpsignature.ParseSignatures([]string{signed.SignatureField()})
	verificationProfile, _ := httpsignature.NewVerificationProfile(httpsignature.VerificationProfileConfig{
		AllowedAlgorithms:  []httpsignature.Algorithm{httpsignature.HMACSHA256},
		RequiredComponents: []httpsignature.ComponentIdentifier{{Name: "@method"}, {Name: "@authority"}},
		Created:            httpsignature.ParameterRequired,
		Expires:            httpsignature.ParameterForbidden,
		AlgorithmParameter: httpsignature.ParameterRequired,
		Nonce:              httpsignature.ParameterForbidden,
		Tag:                httpsignature.ParameterForbidden,
		MaxAge:             time.Minute,
		ClockSkew:          time.Second,
		ResolveTimeout:     time.Second,
		Now:                func() time.Time { return now },
		Resolver: exampleResolver{key: httpsignature.ResolvedKey{
			Algorithm: httpsignature.HMACSHA256, Key: key,
			NotBefore: now.Add(-time.Hour), NotAfter: now.Add(time.Hour), FreshUntil: now.Add(time.Minute),
		}},
	})
	verified, err := httpsignature.NewVerifier(verificationProfile).Verify(
		context.Background(), httpsignature.MessageContext{Request: request}, "sig", inputs, signatures,
	)
	fmt.Println(err == nil, verified.Label, verified.Algorithm)
}
Output:
true sig hmac-sha256

Index

Examples

Constants

View Source
const DefaultMaxSignatureBaseBytes = 1 << 20

DefaultMaxSignatureBaseBytes is the bounded default for direct callers that do not select a stricter per-message limit.

Variables

View Source
var (
	// ErrUnsupportedSignatureAlgorithm reports an unavailable or unregistered algorithm.
	ErrUnsupportedSignatureAlgorithm = errors.New("http signature: unsupported signature algorithm")
	// ErrIncompatibleKey reports a wrong, malformed, or out-of-policy key type.
	ErrIncompatibleKey = errors.New("http signature: incompatible key")
	// ErrInvalidSignatureValue reports cryptographic verification failure.
	ErrInvalidSignatureValue = errors.New("http signature: invalid signature value")
	// ErrSignatureRandomness reports unavailable signing randomness.
	ErrSignatureRandomness = errors.New("http signature: signing randomness unavailable")
)
View Source
var (
	// ErrInvalidBodyIntegration reports incomplete buffered digest policy.
	ErrInvalidBodyIntegration = errors.New("http signature: invalid body digest integration")
	// ErrBodyTooLarge reports that content exceeded its explicit buffering limit.
	ErrBodyTooLarge = errors.New("http signature: body exceeds digest buffer")
	// ErrBodyRead reports a body read or closure failure without retaining
	// potentially sensitive backend details.
	ErrBodyRead = errors.New("http signature: body unavailable for digest")
	// ErrExistingDigest reports a caller-supplied Content-Digest field that this
	// fail-closed adapter refuses to replace.
	ErrExistingDigest = errors.New("http signature: existing Content-Digest rejected")
)
View Source
var (
	// ErrInvalidDigestField reports malformed, empty, or ambiguous digest data.
	ErrInvalidDigestField = errors.New("http signature: invalid digest field")
	// ErrUnsupportedDigestAlgorithm reports an algorithm unavailable for local computation.
	ErrUnsupportedDigestAlgorithm = errors.New("http signature: unsupported digest algorithm")
	// ErrMissingDigest reports that policy selected an algorithm absent from the field.
	ErrMissingDigest = errors.New("http signature: required digest is missing")
	// ErrDigestMismatch reports that content does not match a selected digest.
	ErrDigestMismatch = errors.New("http signature: digest mismatch")
)
View Source
var (
	// ErrInvalidHTTPIntegration reports incomplete adapter configuration.
	ErrInvalidHTTPIntegration = errors.New("http signature: invalid HTTP integration")
	// ErrHTTPIntegrationSigning reports request-signing failure without exposing
	// message or key material.
	ErrHTTPIntegrationSigning = errors.New("http signature: HTTP request signing failed")
	// ErrExistingSignatures reports fields forbidden by adapter policy.
	ErrExistingSignatures = errors.New("http signature: existing signature fields rejected")
	// ErrHTTPIntegrationVerification reports response-verification failure
	// without exposing message or key material.
	ErrHTTPIntegrationVerification = errors.New("http signature: HTTP response verification failed")
	// ErrResponseBodyTooLarge reports that buffered response signing reached its
	// explicit resource limit before any response bytes were emitted.
	ErrResponseBodyTooLarge = errors.New("http signature: response body exceeds signing buffer")
	// ErrAmbiguousProtectedField reports case-colliding map keys for a protected
	// HTTP field whose values cannot be interpreted unambiguously.
	ErrAmbiguousProtectedField = errors.New("http signature: ambiguous protected HTTP field")
)
View Source
var (
	// ErrSignatureBase reports that a covered component cannot be resolved safely.
	ErrSignatureBase = errors.New("http signature: cannot create signature base")
	// ErrSignatureBaseLimit reports that canonicalization exceeded its explicit
	// output bound. It wraps ErrSignatureBase so existing classification remains
	// fail closed.
	ErrSignatureBaseLimit = fmt.Errorf("%w: resource limit exceeded", ErrSignatureBase)
)
View Source
var (
	// ErrReplayDetected reports that the same key and nonce pair was already
	// consumed within its validity window.
	ErrReplayDetected = errors.New("http signature: replay detected")
	// ErrReplayCapacity reports that a bounded replay backend cannot accept a
	// new record. Callers must fail verification closed.
	ErrReplayCapacity = errors.New("http signature: replay store capacity exceeded")
	// ErrInvalidReplayRecord reports an incomplete or out-of-policy record.
	ErrInvalidReplayRecord = errors.New("http signature: invalid replay record")
	// ErrInvalidReplayConfig reports missing or non-positive resource bounds.
	ErrInvalidReplayConfig = errors.New("http signature: invalid replay store configuration")
)
View Source
var (
	// ErrInvalidSignatureInput reports a malformed or semantically invalid
	// Signature-Input field.
	ErrInvalidSignatureInput = errors.New("http signature: invalid Signature-Input field")
	// ErrInvalidSignature reports a malformed or semantically invalid Signature
	// field.
	ErrInvalidSignature = errors.New("http signature: invalid Signature field")
	// ErrInvalidAcceptSignature reports a malformed or semantically invalid
	// Accept-Signature field.
	ErrInvalidAcceptSignature = errors.New("http signature: invalid Accept-Signature field")
)
View Source
var (
	// ErrInvalidSigningProfile reports an incomplete or contradictory signing
	// policy.
	ErrInvalidSigningProfile = errors.New("http signature: invalid signing profile")
	// ErrSigningPolicy reports that a signing request violates its profile.
	ErrSigningPolicy = errors.New("http signature: signing policy rejected request")
	// ErrSigningKey reports unavailable, expired, revoked, mismatched, or
	// incompatible signing material.
	ErrSigningKey = errors.New("http signature: signing key unavailable")
	// ErrSigningProvider reports a provider failure without retaining backend
	// details in the public error chain.
	ErrSigningProvider = errors.New("http signature: signing key provider failed")
	// ErrSigningBase reports signature-base construction failure.
	ErrSigningBase = errors.New("http signature: signing base unavailable")
	// ErrSigningCryptographic reports failure of the selected signing primitive.
	ErrSigningCryptographic = errors.New("http signature: cryptographic signing failed")
	// ErrInvalidSignedFields reports an empty, malformed, mismatched, or
	// duplicate set supplied for deterministic field combination.
	ErrInvalidSignedFields = errors.New("http signature: invalid signed fields")
)
View Source
var (
	// ErrInvalidSyntaxLimits reports missing or contradictory parser bounds.
	ErrInvalidSyntaxLimits = errors.New("http signature: invalid syntax limits")
	// ErrSyntaxLimit reports input rejected by an explicit parser bound.
	ErrSyntaxLimit = errors.New("http signature: syntax resource limit exceeded")
)
View Source
var (
	// ErrInvalidVerificationProfile reports an incomplete or contradictory
	// application policy.
	ErrInvalidVerificationProfile = errors.New("http signature: invalid verification profile")
	// ErrKeyNotFound allows resolvers to distinguish an unknown identifier from
	// transient backend failure without disclosing the identifier.
	ErrKeyNotFound = errors.New("http signature: verification key not found")
	// ErrKeyResolutionFailure reports a resolver failure whose backend details
	// are deliberately not retained in the public error chain.
	ErrKeyResolutionFailure = errors.New("http signature: verification key resolution failed")
	// ErrReplayBackendFailure reports an unknown replay-backend outcome whose
	// details are deliberately not retained in the public error chain.
	ErrReplayBackendFailure = errors.New("http signature: replay backend failed")
)
View Source
var ErrInvalidDigestPreferences = errors.New("http signature: invalid digest preferences")

ErrInvalidDigestPreferences reports a malformed RFC 9530 integrity preference dictionary.

Functions

func CombineSignedFields

func CombineSignedFields(fields ...SignedFields) (SignatureInputs, Signatures, error)

CombineSignedFields combines validated label pairs in caller order. It rejects duplicate labels and never uses map iteration to choose wire order.

func CreateSignatureBase

func CreateSignatureBase(context MessageContext, input SignatureInput) (string, error)

CreateSignatureBase resolves the ordered covered components and produces the exact RFC 9421 signature base. It returns no partial base on error.

func Sign

func Sign(ctx context.Context, algorithm Algorithm, key any, signatureBase []byte, random io.Reader) ([]byte, error)

Sign applies the exact RFC 9421 algorithm to signatureBase. RSA moduli must contain 2048 through 8192 bits. Randomized algorithms use Go-managed cryptographically secure randomness. random is retained for source compatibility and ignored.

func Verify

func Verify(ctx context.Context, algorithm Algorithm, key any, signatureBase, signature []byte) error

Verify applies the exact RFC 9421 algorithm and returns only typed, secret-safe errors. RSA moduli must contain 2048 through 8192 bits. Verification keys must be public key types; RSA or ECDSA private keys are deliberately rejected.

Types

type AcceptSignatures

type AcceptSignatures struct {
	// contains filtered or unexported fields
}

AcceptSignatures is an immutable ordered Accept-Signature field.

func ParseAcceptSignatures

func ParseAcceptSignatures(values []string) (AcceptSignatures, error)

ParseAcceptSignatures parses requested covered components and metadata. The created and expires parameters are Boolean requests rather than timestamps.

func ParseAcceptSignaturesWithLimits

func ParseAcceptSignaturesWithLimits(values []string, limits SyntaxLimits) (AcceptSignatures, error)

ParseAcceptSignaturesWithLimits parses Accept-Signature under explicit resource bounds.

func (AcceptSignatures) Entries

func (requests AcceptSignatures) Entries() []SignatureRequest

Entries returns a deep copy in combined-field wire order.

func (AcceptSignatures) String

func (requests AcceptSignatures) String() string

String returns the canonical Structured Fields serialization.

type Algorithm

type Algorithm string

Algorithm is an active IANA HTTP Signature Algorithms registry key.

const (
	// RSAPSSSHA512 is RSASSA-PSS with SHA-512, MGF1-SHA-512, and 64-byte salt.
	RSAPSSSHA512 Algorithm = "rsa-pss-sha512"
	// RSAV15SHA256 is RSASSA-PKCS1-v1_5 with SHA-256.
	RSAV15SHA256 Algorithm = "rsa-v1_5-sha256"
	// HMACSHA256 is HMAC with SHA-256.
	HMACSHA256 Algorithm = "hmac-sha256"
	// ECDSAP256SHA256 is P-256 ECDSA with SHA-256 and IEEE P1363 encoding.
	ECDSAP256SHA256 Algorithm = "ecdsa-p256-sha256"
	// ECDSAP384SHA384 is P-384 ECDSA with SHA-384 and IEEE P1363 encoding.
	ECDSAP384SHA384 Algorithm = "ecdsa-p384-sha384"
	// Ed25519 is pure Ed25519 with no prehash.
	Ed25519 Algorithm = "ed25519"
)

type BufferedContentDigestRoundTripper

type BufferedContentDigestRoundTripper struct {
	// contains filtered or unexported fields
}

BufferedContentDigestRoundTripper consumes and closes the caller request body, then delegates a cloned request with a replayable buffered body. It is intended to wrap a SigningRoundTripper when Content-Digest must be covered: digest transport outside, signing transport inside, network transport last.

func NewBufferedContentDigestRoundTripper

func NewBufferedContentDigestRoundTripper(config BufferedContentDigestRoundTripperConfig) (*BufferedContentDigestRoundTripper, error)

NewBufferedContentDigestRoundTripper validates explicit algorithms and a positive resource limit.

func (*BufferedContentDigestRoundTripper) RoundTrip

func (transport *BufferedContentDigestRoundTripper) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper with fail-closed body ownership.

type BufferedContentDigestRoundTripperConfig

type BufferedContentDigestRoundTripperConfig struct {
	Transport  http.RoundTripper
	Algorithms []DigestAlgorithm
	MaxBytes   int64
}

BufferedContentDigestRoundTripperConfig defines eager Content-Digest generation. It hashes the HTTP content bytes presented to the transport, after any application-managed content coding.

type BufferedContentDigestVerificationMiddleware

type BufferedContentDigestVerificationMiddleware func(http.Handler) http.Handler

BufferedContentDigestVerificationMiddleware wraps an http.Handler.

func NewBufferedContentDigestVerificationMiddleware

func NewBufferedContentDigestVerificationMiddleware(config BufferedContentDigestVerificationMiddlewareConfig) (BufferedContentDigestVerificationMiddleware, error)

NewBufferedContentDigestVerificationMiddleware validates an explicit, bounded inbound digest policy.

type BufferedContentDigestVerificationMiddlewareConfig

type BufferedContentDigestVerificationMiddlewareConfig struct {
	RequiredAlgorithms []DigestAlgorithm
	MaxBytes           int64
	MapError           func(http.ResponseWriter, *http.Request, error)
}

BufferedContentDigestVerificationMiddlewareConfig defines eager inbound Content-Digest verification. MapError owns application-specific HTTP status and disclosure behavior.

type BufferedTrailerVerificationMiddleware

type BufferedTrailerVerificationMiddleware func(http.Handler) http.Handler

BufferedTrailerVerificationMiddleware wraps an http.Handler.

func NewBufferedTrailerVerificationMiddleware

func NewBufferedTrailerVerificationMiddleware(config BufferedTrailerVerificationMiddlewareConfig) (BufferedTrailerVerificationMiddleware, error)

NewBufferedTrailerVerificationMiddleware validates a bounded trailer policy. It requires the verification profile to cover content-digest with tr so a successful result authenticates the digest that was checked.

type BufferedTrailerVerificationMiddlewareConfig

type BufferedTrailerVerificationMiddlewareConfig struct {
	Verifier           *Verifier
	SelectLabel        func(*http.Request, SignatureInputs, Signatures) (string, error)
	RequiredAlgorithms []DigestAlgorithm
	MaxBytes           int64
	ExternalContext    func(context.Context, *http.Request) (*ExternalRequestContext, error)
	MapError           func(http.ResponseWriter, *http.Request, error)
}

BufferedTrailerVerificationMiddlewareConfig defines eager processing for a request whose Content-Digest and message signature arrive in trailers.

type BufferedTrailerVerifyingRoundTripper

type BufferedTrailerVerifyingRoundTripper struct {
	// contains filtered or unexported fields
}

BufferedTrailerVerifyingRoundTripper verifies response trailers after EOF and replaces the consumed body with a replayable in-memory copy. It closes the received response body on every success and failure path.

func NewBufferedTrailerVerifyingRoundTripper

func NewBufferedTrailerVerifyingRoundTripper(config BufferedTrailerVerifyingRoundTripperConfig) (*BufferedTrailerVerifyingRoundTripper, error)

NewBufferedTrailerVerifyingRoundTripper validates an explicit bounded response-trailer policy. The profile must authenticate Content-Digest with the tr parameter.

func (*BufferedTrailerVerifyingRoundTripper) RoundTrip

func (transport *BufferedTrailerVerifyingRoundTripper) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper. Trailer loss, digest mismatch, and signature failure close the response body and return no response.

type BufferedTrailerVerifyingRoundTripperConfig

type BufferedTrailerVerifyingRoundTripperConfig struct {
	Transport          http.RoundTripper
	Verifier           *Verifier
	SelectLabel        func(*http.Request, *http.Response, SignatureInputs, Signatures) (string, error)
	RequiredAlgorithms []DigestAlgorithm
	MaxBytes           int64
	ExternalContext    func(context.Context, *http.Request, *http.Response) (*ExternalRequestContext, error)
}

BufferedTrailerVerifyingRoundTripperConfig defines eager response processing when Content-Digest and the message signature arrive in trailers. The body is not returned to the caller until its bounded digest and signature verify.

type ComponentIdentifier

type ComponentIdentifier struct {
	Name       string
	Parameters []Parameter
}

ComponentIdentifier identifies one ordered covered message component.

func (ComponentIdentifier) Parameter

func (component ComponentIdentifier) Parameter(name string) (any, bool)

Parameter returns a copy of the named component parameter.

type Digest

type Digest struct {
	Algorithm  DigestAlgorithm
	Value      []byte
	Parameters []Parameter
}

Digest is one algorithm and checksum member of an RFC 9530 integrity field.

type DigestAlgorithm

type DigestAlgorithm string

DigestAlgorithm is an RFC 9530 Hash Algorithms for HTTP Digest Fields key.

const (
	// SHA256 identifies the active sha-256 digest algorithm.
	SHA256 DigestAlgorithm = "sha-256"
	// SHA512 identifies the active sha-512 digest algorithm.
	SHA512 DigestAlgorithm = "sha-512"
)

type DigestField

type DigestField struct {
	// contains filtered or unexported fields
}

DigestField is an ordered, immutable RFC 9530 integrity-field dictionary. Parsed fields preserve wire order; locally computed fields use algorithm-key order so output does not depend on caller or map iteration order.

func ComputeDigests

func ComputeDigests(algorithms []DigestAlgorithm, content []byte) (DigestField, error)

ComputeDigests calculates an integrity field over content using active algorithms from the RFC 9530 registry. At least one unique algorithm is required.

func ParseDigestField

func ParseDigestField(value string) (DigestField, error)

ParseDigestField parses the RFC 9530 Dictionary form used by Content-Digest and Repr-Digest. It rejects duplicate keys and values other than Structured Fields Byte Sequences.

func ParseDigestFields

func ParseDigestFields(values []string) (DigestField, error)

ParseDigestFields combines and parses all field lines for one Content-Digest or Repr-Digest field. Duplicate algorithm keys are rejected across lines.

func ParseDigestFieldsWithLimits

func ParseDigestFieldsWithLimits(values []string, limits SyntaxLimits) (DigestField, error)

ParseDigestFieldsWithLimits combines and parses integrity field lines under explicit resource bounds.

func (DigestField) Entries

func (field DigestField) Entries() []Digest

Entries returns a deep copy of the ordered digest members.

func (DigestField) String

func (field DigestField) String() string

String serializes the digest dictionary using canonical Byte Sequence encoding and the field's stable member order.

func (DigestField) Verify

func (field DigestField) Verify(content []byte, required []DigestAlgorithm) error

Verify computes and constant-time compares every policy-selected digest. Unknown, unselected field members are retained but ignored as RFC 9530 permits recipients to ignore any digest.

type DigestPreference

type DigestPreference struct {
	Algorithm DigestAlgorithm
	Weight    int64
}

DigestPreference is one algorithm and relative weight from a Want-Content-Digest or Want-Repr-Digest field. Weight is in the inclusive range 0 through 10; zero means not acceptable.

type DigestPreferences

type DigestPreferences struct {
	// contains filtered or unexported fields
}

DigestPreferences is an immutable ordered RFC 9530 integrity preference dictionary. Order is preserved because equal weights have no protocol-level tie-breaking semantics.

func NewDigestPreferences

func NewDigestPreferences(entries []DigestPreference) (DigestPreferences, error)

NewDigestPreferences validates and copies an ordered preference dictionary.

func ParseDigestPreferences

func ParseDigestPreferences(values []string) (DigestPreferences, error)

ParseDigestPreferences parses combined Want-Content-Digest or Want-Repr-Digest field lines. Unknown algorithm keys are retained for application policy and interoperability.

func ParseDigestPreferencesWithLimits

func ParseDigestPreferencesWithLimits(values []string, limits SyntaxLimits) (DigestPreferences, error)

ParseDigestPreferencesWithLimits parses integrity preferences under explicit resource bounds.

func (DigestPreferences) Entries

func (preferences DigestPreferences) Entries() []DigestPreference

Entries returns a copy in combined-field wire order.

func (DigestPreferences) String

func (preferences DigestPreferences) String() string

String returns the canonical Structured Fields serialization.

type ExistingSignaturesPolicy

type ExistingSignaturesPolicy uint8

ExistingSignaturesPolicy controls how a signing transport handles fields already present on a caller request. The zero value is invalid.

const (
	// ExistingSignaturesReject prevents accidental overwrite or signature
	// confusion.
	ExistingSignaturesReject ExistingSignaturesPolicy = iota + 1
	// ExistingSignaturesAppend parses, validates, and preserves existing label
	// order before appending the new signature.
	ExistingSignaturesAppend
)

type ExternalRequestContext

type ExternalRequestContext struct {
	Scheme        string
	Authority     string
	RequestTarget string
}

ExternalRequestContext is trusted request-target information supplied by an application that terminates HTTP behind an intermediary. Values are never inferred from Forwarded or X-Forwarded-* fields.

type HMACKey

type HMACKey struct {
	// contains filtered or unexported fields
}

HMACKey owns copied HMAC key bytes. Keys contain between 256 and 512 bits. The lower bound matches the HMAC-SHA-256 output size; the upper bound matches its block size, beyond which HMAC hashes the key before use.

func NewHMACKey

func NewHMACKey(material []byte) (HMACKey, error)

NewHMACKey copies caller key material and enforces the HMACKey size bounds.

type KeyResolver

type KeyResolver interface {
	Resolve(context.Context, string) (ResolvedKey, error)
}

KeyResolver resolves an opaque key identifier under the supplied bounded context. Implementations must return only context-aware, bounded operations.

type MemoryReplayConfig

type MemoryReplayConfig struct {
	// Capacity is the maximum number of retained key and nonce identities.
	Capacity int
	// MaxTTL is the longest accepted interval from Now to ExpiresAt.
	MaxTTL time.Duration
	// MaxKeyIDBytes and MaxNonceBytes bound caller-controlled identity storage.
	MaxKeyIDBytes int
	MaxNonceBytes int
	// Now must be safe for concurrent use and must return promptly. The store
	// never invokes it while holding replay state.
	Now func() time.Time
}

MemoryReplayConfig defines mandatory resource bounds and the caller-owned clock for a process-local replay store. String limits count bytes, not Unicode code points. It is not a distributed replay guarantee.

type MemoryReplayStore

type MemoryReplayStore struct {
	// contains filtered or unexported fields
}

MemoryReplayStore is a bounded process-local ReplayStore. It starts no goroutines. Consume removes at most one unrelated expired identity and uses an expiration heap, so cleanup work is bounded and never scans all records. Concurrent clock observations are clamped so store time never moves backward. Copies refer to the same synchronized replay state.

func NewMemoryReplayStore

func NewMemoryReplayStore(config MemoryReplayConfig) (*MemoryReplayStore, error)

NewMemoryReplayStore constructs a process-local store only when all resource bounds and the clock are explicitly supplied.

func (*MemoryReplayStore) Consume

func (store *MemoryReplayStore) Consume(ctx context.Context, record ReplayRecord) error

Consume atomically reserves record until its expiration. It performs a constant number of O(log Capacity) heap operations and never scans every retained identity. Caller-owned clock and context methods run without the replay lock held. Cancellation observed while waiting for replay state returns the context error without consuming the record; cancellation racing after lock acquisition may lose to a successful reservation.

type MessageContext

type MessageContext struct {
	Request           *http.Request
	Response          *http.Response
	RelatedRequest    *http.Request
	ExternalRequest   *ExternalRequestContext
	StructuredFields  map[string]StructuredFieldType
	ResponseTransport ResponseTransportMode
	// MaxSignatureBaseBytes bounds the complete canonical base. Zero selects
	// DefaultMaxSignatureBaseBytes; negative values are invalid.
	MaxSignatureBaseBytes int
}

MessageContext supplies the target message and optional related request. Exactly one of Request and Response must be set. RelatedRequest is required when a response signature covers a component carrying the req parameter.

type Parameter

type Parameter struct {
	Name  string
	Value any
}

Parameter is an ordered Structured Fields parameter. Value is one of bool, string, int64, float64, []byte, or SFToken. Byte values are always copied at API boundaries.

type ParameterPolicy

type ParameterPolicy uint8

ParameterPolicy specifies whether one registered signature parameter is prohibited, accepted, or mandatory. The zero value is invalid so profiles cannot accidentally inherit a permissive default.

const (
	ParameterForbidden ParameterPolicy = iota + 1
	ParameterOptional
	ParameterRequired
)

type ReplayRecord

type ReplayRecord struct {
	KeyID     string
	Nonce     string
	ExpiresAt time.Time
}

ReplayRecord identifies one verification attempt until ExpiresAt. KeyID and Nonce are treated as opaque values and are never included in errors.

type ReplayStore

type ReplayStore interface {
	Consume(context.Context, ReplayRecord) error
}

ReplayStore atomically consumes a signature nonce. A durable implementation must make concurrent Consume calls for the same key and nonce linearizable: exactly one call succeeds before expiration and all others return ErrReplayDetected. Unknown backend outcomes must return an error, never nil.

type RequestVerificationMiddleware

type RequestVerificationMiddleware func(http.Handler) http.Handler

RequestVerificationMiddleware wraps an http.Handler.

func NewRequestVerificationMiddleware

func NewRequestVerificationMiddleware(config RequestVerificationMiddlewareConfig) (RequestVerificationMiddleware, error)

NewRequestVerificationMiddleware validates an inbound adapter. It supplies no status-code or disclosure defaults; MapError owns application mapping.

type RequestVerificationMiddlewareConfig

type RequestVerificationMiddlewareConfig struct {
	Verifier        *Verifier
	SelectLabel     func(*http.Request, SignatureInputs, Signatures) (string, error)
	ExternalContext func(context.Context, *http.Request) (*ExternalRequestContext, error)
	MapError        func(http.ResponseWriter, *http.Request, error)
}

RequestVerificationMiddlewareConfig defines inbound selection, trusted external-origin reconstruction, and application-specific failure mapping.

type ResolvedKey

type ResolvedKey struct {
	Algorithm  Algorithm
	Key        any
	NotBefore  time.Time
	NotAfter   time.Time
	FreshUntil time.Time
	Revoked    bool
}

ResolvedKey binds verification material to exactly one algorithm and an explicit validity and cache-freshness interval. Resolver implementations own storage, rotation, revocation lookup, caching, and remote IO.

type ResponseSigningMiddleware

type ResponseSigningMiddleware func(http.Handler) http.Handler

ResponseSigningMiddleware wraps an http.Handler.

func NewResponseSigningMiddleware

func NewResponseSigningMiddleware(config ResponseSigningMiddlewareConfig) (ResponseSigningMiddleware, error)

NewResponseSigningMiddleware validates an explicit response-signing policy. Configuration, mapping, and reporting callbacks and the signing profile must be safe for concurrent handler calls.

type ResponseSigningMiddlewareConfig

type ResponseSigningMiddlewareConfig struct {
	Signer                  *Signer
	Label                   string
	Existing                ExistingSignaturesPolicy
	MaxBufferedBytes        int64
	ContentDigestAlgorithms []DigestAlgorithm
	Options                 func(context.Context, *http.Request, *http.Response) (SigningOptions, error)
	ExternalContext         func(context.Context, *http.Request, *http.Response) (*ExternalRequestContext, error)
	MapError                func(http.ResponseWriter, *http.Request, error)
	ReportError             func(*http.Request, error)
}

ResponseSigningMiddlewareConfig defines a fail-closed buffered response signing boundary. MaxBufferedBytes and ReportError are mandatory; the latter records redacted output failures after signed headers have committed. Handlers requiring streaming, flushing, hijacking, or full-duplex operation need a trailer-aware adapter instead.

type ResponseTransportMode

type ResponseTransportMode uint8

ResponseTransportMode selects the net/http response representation whose transport-managed fields are covered by a signature.

const (
	// ResponseTransportUnspecified accepts a managed response field only when
	// the received and Response.Write representations are provably identical.
	ResponseTransportUnspecified ResponseTransportMode = iota
	// ResponseTransportReceived covers a response parsed by net/http or returned
	// by a RoundTripper. Preserved Header values carry received field identity.
	ResponseTransportReceived
	// ResponseTransportWrite covers the deterministic output of Response.Write.
	ResponseTransportWrite
)

type SFToken

type SFToken string

SFToken is an RFC 8941 Structured Fields Token parameter value.

type SignatureInput

type SignatureInput struct {
	Label      string
	Components []ComponentIdentifier
	Parameters []Parameter
}

SignatureInput is one labeled Signature-Input dictionary member.

func (SignatureInput) Parameter

func (input SignatureInput) Parameter(name string) (any, bool)

Parameter returns a copy of the named signature parameter.

type SignatureInputs

type SignatureInputs struct {
	// contains filtered or unexported fields
}

SignatureInputs is an immutable ordered Signature-Input field.

func ParseSignatureInputs

func ParseSignatureInputs(values []string) (SignatureInputs, error)

ParseSignatureInputs parses and semantically validates combined Signature-Input field lines. It preserves dictionary, component, and parameter order and rejects duplicate labels before Structured Fields dictionary replacement semantics could hide them.

func ParseSignatureInputsWithLimits

func ParseSignatureInputsWithLimits(values []string, limits SyntaxLimits) (SignatureInputs, error)

ParseSignatureInputsWithLimits parses Signature-Input under explicit resource bounds.

func (SignatureInputs) Entries

func (inputs SignatureInputs) Entries() []SignatureInput

Entries returns a deep copy in combined-field wire order.

func (SignatureInputs) String

func (inputs SignatureInputs) String() string

String returns the canonical Structured Fields serialization.

type SignatureRequest

type SignatureRequest = SignatureInput

SignatureRequest is one requested signature from an Accept-Signature field.

type SignatureValue

type SignatureValue struct {
	Label      string
	Value      []byte
	Parameters []Parameter
}

SignatureValue is one labeled Signature dictionary member.

type Signatures

type Signatures struct {
	// contains filtered or unexported fields
}

Signatures is an immutable ordered Signature field.

func ParseSignatures

func ParseSignatures(values []string) (Signatures, error)

ParseSignatures parses and semantically validates combined Signature field lines, preserving label order and rejecting duplicate labels.

func ParseSignaturesWithLimits

func ParseSignaturesWithLimits(values []string, limits SyntaxLimits) (Signatures, error)

ParseSignaturesWithLimits parses Signature under explicit resource bounds.

func (Signatures) Entries

func (signatures Signatures) Entries() []SignatureValue

Entries returns a deep copy in combined-field wire order.

func (Signatures) String

func (signatures Signatures) String() string

String returns the canonical Structured Fields serialization.

type SignedFields

type SignedFields struct {
	// contains filtered or unexported fields
}

SignedFields owns one matching Signature-Input and Signature label pair.

func (SignedFields) SignatureField

func (signed SignedFields) SignatureField() string

SignatureField returns a complete canonical field value for this label.

func (SignedFields) SignatureInputField

func (signed SignedFields) SignatureInputField() string

SignatureInputField returns a complete canonical field value for this label.

type Signer

type Signer struct {
	// contains filtered or unexported fields
}

Signer applies one immutable application signing profile.

func NewSigner

func NewSigner(profile *SigningProfile) *Signer

NewSigner creates a signer with no hidden defaults or network access.

func (*Signer) Sign

func (signer *Signer) Sign(ctx context.Context, message MessageContext, label string, options SigningOptions) (SignedFields, error)

Sign creates one matching signature field pair without mutating the HTTP message or consuming its body.

type SigningKey

type SigningKey struct {
	KeyID     string
	Algorithm Algorithm
	Key       any
	NotBefore time.Time
	NotAfter  time.Time
	Revoked   bool
}

SigningKey binds private or shared signing material to an identifier, algorithm, validity interval, and revocation decision.

type SigningKeyProvider

type SigningKeyProvider interface {
	SigningKey(context.Context) (SigningKey, error)
}

SigningKeyProvider selects current signing material under a bounded context. Implementations own key storage and rotation; the core performs no IO.

type SigningOptions

type SigningOptions struct {
	Nonce string
}

SigningOptions supplies per-message values that cannot be safely defaulted.

type SigningProfile

type SigningProfile struct {
	// contains filtered or unexported fields
}

SigningProfile is an immutable application signing policy.

func NewSigningProfile

func NewSigningProfile(config SigningProfileConfig) (*SigningProfile, error)

NewSigningProfile validates and copies an explicit signing policy.

type SigningProfileConfig

type SigningProfileConfig struct {
	AllowedAlgorithms  []Algorithm
	CoveredComponents  []ComponentIdentifier
	AllowEmptyCoverage bool
	Expires            ParameterPolicy
	AlgorithmParameter ParameterPolicy
	Nonce              ParameterPolicy
	Tag                ParameterPolicy
	TagValue           string
	Lifetime           time.Duration
	ResolveTimeout     time.Duration
	Now                func() time.Time
	Provider           SigningKeyProvider
	// Random is retained for source compatibility.
	//
	// Deprecated: Random is ignored. Randomized algorithms use Go-managed
	// cryptographically secure randomness.
	Random                        io.Reader
	RequireExternalRequestContext bool
}

SigningProfileConfig defines all signing decisions. Creation time and keyid are always included as required by this signing API. Other registered parameters must be explicitly required or forbidden.

type SigningRoundTripper

type SigningRoundTripper struct {
	// contains filtered or unexported fields
}

SigningRoundTripper signs a cloned request immediately before delegation. It does not read or replace Body; the wrapped transport retains normal body consumption and closure ownership.

func NewSigningRoundTripper

func NewSigningRoundTripper(config SigningRoundTripperConfig) (*SigningRoundTripper, error)

NewSigningRoundTripper validates an explicit outbound adapter configuration.

func (*SigningRoundTripper) RoundTrip

func (transport *SigningRoundTripper) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper without mutating request headers.

type SigningRoundTripperConfig

type SigningRoundTripperConfig struct {
	Transport       http.RoundTripper
	Signer          *Signer
	Label           string
	Existing        ExistingSignaturesPolicy
	Options         func(context.Context, *http.Request) (SigningOptions, error)
	ExternalContext func(context.Context, *http.Request) (*ExternalRequestContext, error)
}

SigningRoundTripperConfig defines an outbound request-signing boundary. Transport, options, label, and existing-field policy are all explicit.

type StructuredFieldType

type StructuredFieldType uint8

StructuredFieldType describes the application-known RFC 8941 field shape required by the sf component parameter.

const (
	// StructuredFieldDictionary identifies an RFC 8941 Dictionary field.
	StructuredFieldDictionary StructuredFieldType = iota + 1
	// StructuredFieldList identifies an RFC 8941 List field.
	StructuredFieldList
	// StructuredFieldItem identifies an RFC 8941 Item field.
	StructuredFieldItem
)

type SyntaxLimits

type SyntaxLimits struct {
	MaxFieldBytes             int
	MaxFieldLines             int
	MaxDictionaryMembers      int
	MaxComponentsPerSignature int
	MaxParametersPerItem      int
	MaxBinaryBytes            int
}

SyntaxLimits bounds untrusted Structured Fields before and after parsing. Limits are per logical combined field.

func DefaultSyntaxLimits

func DefaultSyntaxLimits() SyntaxLimits

DefaultSyntaxLimits returns the restrictive bound used by convenience parsers. A fresh value prevents mutable package-global parser policy.

func (SyntaxLimits) Validate

func (limits SyntaxLimits) Validate() error

Validate checks that every resource dimension has a positive bound.

type TrailerResponseSigningMiddleware

type TrailerResponseSigningMiddleware func(http.Handler) http.Handler

TrailerResponseSigningMiddleware wraps an http.Handler. Recipients must wait for EOF and reject a response whose declared digest or signature trailers are absent. Configuration callbacks and ReportError must be concurrency-safe.

func NewTrailerResponseSigningMiddleware

func NewTrailerResponseSigningMiddleware(config TrailerResponseSigningMiddlewareConfig) (TrailerResponseSigningMiddleware, error)

NewTrailerResponseSigningMiddleware validates an explicit streaming policy. The signing profile must cover Content-Digest with the tr parameter.

type TrailerResponseSigningMiddlewareConfig

type TrailerResponseSigningMiddlewareConfig struct {
	Signer          *Signer
	Label           string
	Algorithms      []DigestAlgorithm
	MaxBytes        int64
	Options         func(context.Context, *http.Request) (SigningOptions, error)
	ExternalContext func(context.Context, *http.Request) (*ExternalRequestContext, error)
	ReportError     func(*http.Request, error)
}

TrailerResponseSigningMiddlewareConfig defines streaming response signing. ReportError is required because a size, handler-write, key, randomness, or signing failure can occur after response bytes have already been emitted.

type TrailerSigningRoundTripper

type TrailerSigningRoundTripper struct {
	// contains filtered or unexported fields
}

TrailerSigningRoundTripper streams one non-replayable request attempt. It does not pre-read the body. Size, hash, key, or signing failure during Read aborts the attempt; bytes returned by earlier reads may already be on wire. A response is released only after EOF finalization succeeds.

func NewTrailerSigningRoundTripper

func NewTrailerSigningRoundTripper(config TrailerSigningRoundTripperConfig) (*TrailerSigningRoundTripper, error)

NewTrailerSigningRoundTripper validates a streaming trailer policy.

func (*TrailerSigningRoundTripper) RoundTrip

func (transport *TrailerSigningRoundTripper) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper. The wrapped transport owns the body while active; an early successful response is closed and rejected, and the adapter closes the unfinished request body.

type TrailerSigningRoundTripperConfig

type TrailerSigningRoundTripperConfig struct {
	Transport       http.RoundTripper
	Signer          *Signer
	Label           string
	Algorithms      []DigestAlgorithm
	MaxBytes        int64
	Options         func(context.Context, *http.Request) (SigningOptions, error)
	ExternalContext func(context.Context, *http.Request) (*ExternalRequestContext, error)
}

TrailerSigningRoundTripperConfig defines a streaming request adapter that emits Content-Digest, Signature-Input, and Signature in trailers after EOF. The signing profile must cover content-digest with the tr parameter.

type VerificationError

type VerificationError struct {
	Failure VerificationFailure
	// contains filtered or unexported fields
}

VerificationError is safe for classification and logging. Error omits key identifiers, nonces, signature bases, signature bytes, and message content.

func (*VerificationError) Error

func (err *VerificationError) Error() string

func (*VerificationError) Unwrap

func (err *VerificationError) Unwrap() error

Unwrap supports errors.Is and errors.As without including the cause in the rendered error string.

type VerificationFailure

type VerificationFailure string

VerificationFailure is a stable, application-mappable failure category.

const (
	VerificationSelection     VerificationFailure = "selection"
	VerificationPolicy        VerificationFailure = "policy"
	VerificationTime          VerificationFailure = "time"
	VerificationKeyResolution VerificationFailure = "key-resolution"
	VerificationKey           VerificationFailure = "key"
	VerificationAlgorithm     VerificationFailure = "algorithm"
	VerificationBase          VerificationFailure = "signature-base"
	VerificationCryptographic VerificationFailure = "cryptographic"
	VerificationReplay        VerificationFailure = "replay"
)

type VerificationProfile

type VerificationProfile struct {
	// contains filtered or unexported fields
}

VerificationProfile is an immutable application verification policy.

func NewVerificationProfile

func NewVerificationProfile(config VerificationProfileConfig) (*VerificationProfile, error)

NewVerificationProfile validates and copies an explicit application policy.

type VerificationProfileConfig

type VerificationProfileConfig struct {
	AllowedAlgorithms             []Algorithm
	RequiredComponents            []ComponentIdentifier
	AllowEmptyCoverage            bool
	Created                       ParameterPolicy
	Expires                       ParameterPolicy
	AlgorithmParameter            ParameterPolicy
	Nonce                         ParameterPolicy
	Tag                           ParameterPolicy
	AllowedTags                   []string
	MaxAge                        time.Duration
	ClockSkew                     time.Duration
	ResolveTimeout                time.Duration
	ReplayTimeout                 time.Duration
	Now                           func() time.Time
	Resolver                      KeyResolver
	Replay                        ReplayStore
	RequireExternalRequestContext bool
}

VerificationProfileConfig defines the application decisions RFC 9421 leaves to a profile. Key identifiers are mandatory in this profile implementation; static keys can be exposed by a resolver that recognizes a fixed identifier.

type VerifiedSignature

type VerifiedSignature struct {
	Label     string
	KeyID     string
	Algorithm Algorithm
	Created   time.Time
	Expires   time.Time
}

VerifiedSignature reports the selected label and resolved public metadata. A successful result proves cryptographic validity and profile conformance; it does not grant authentication or authorization.

func VerifiedSignatureFromContext

func VerifiedSignatureFromContext(ctx context.Context) (VerifiedSignature, bool)

VerifiedSignatureFromContext returns profile-conformant verification metadata stored by RequestVerificationMiddleware. It is not an authorization result.

func VerifiedSignatureFromResponse

func VerifiedSignatureFromResponse(response *http.Response) (VerifiedSignature, bool)

VerifiedSignatureFromResponse returns profile-conformant verification metadata stored by VerifyingRoundTripper.

type Verifier

type Verifier struct {
	// contains filtered or unexported fields
}

Verifier applies one immutable application profile.

func NewVerifier

func NewVerifier(profile *VerificationProfile) *Verifier

NewVerifier creates a verifier with no hidden defaults or network access.

func (*Verifier) Verify

func (verifier *Verifier) Verify(
	ctx context.Context,
	message MessageContext,
	label string,
	inputs SignatureInputs,
	signatures Signatures,
) (VerifiedSignature, error)

Verify selects one explicit label, enforces application policy, resolves an algorithm-bound key, verifies the reconstructed signature base, and only then atomically consumes the nonce.

type VerifyingRoundTripper

type VerifyingRoundTripper struct {
	// contains filtered or unexported fields
}

VerifyingRoundTripper verifies response signatures. A selected signature that covers a response Content-Digest is accepted only when an explicit bounded digest policy verifies and replaces the consumed body.

func NewVerifyingRoundTripper

func NewVerifyingRoundTripper(config VerifyingRoundTripperConfig) (*VerifyingRoundTripper, error)

NewVerifyingRoundTripper validates an explicit response-verification adapter.

func (*VerifyingRoundTripper) RoundTrip

func (transport *VerifyingRoundTripper) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper. A successful verification is stored on a cloned response Request context and is not an authorization result.

type VerifyingRoundTripperConfig

type VerifyingRoundTripperConfig struct {
	Transport               http.RoundTripper
	Verifier                *Verifier
	SelectLabel             func(*http.Request, *http.Response, SignatureInputs, Signatures) (string, error)
	ContentDigestAlgorithms []DigestAlgorithm
	MaxBufferedBytes        int64
	ExternalContext         func(context.Context, *http.Request, *http.Response) (*ExternalRequestContext, error)
}

VerifyingRoundTripperConfig defines response signature selection and trusted external request context. The wrapped transport retains request-body ownership; this adapter closes a response body when verification fails.

Directories

Path Synopsis
Package compatibility isolates non-RFC 9421 HTTP authentication schemes behind caller-supplied protocol implementations.
Package compatibility isolates non-RFC 9421 HTTP authentication schemes behind caller-supplied protocol implementations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL