Documentation ¶
Overview ¶
Package httpsig signs and verifies HTTP requests (with body digests) according to the "HTTP Message Signatures" draft standard https://datatracker.ietf.org/doc/draft-ietf-httpbis-message-signatures/
Example (Round_trip) ¶
// BSD 3-Clause License // Copyright (c) 2021, James Bowes // Copyright (c) 2023, Alexander Taraymovich, OffBlocks // All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package main import ( "fmt" "io" "net/http" "time" "github.com/offblocks/httpsig" ) const secret = "support-your-local-cat-bonnet-store" func main() { h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") _, _ = io.WriteString(w, "Your request has a valid signature!") }) middleware := httpsig.NewVerifyMiddleware(httpsig.WithHmacSha256("key1", []byte(secret))) http.Handle("/", middleware(h)) go func() { _ = http.ListenAndServe("127.0.0.1:1234", http.DefaultServeMux) }() // Give the server time to sleep. Terrible, I know. time.Sleep(100 * time.Millisecond) client := http.Client{ // Wrap the transport: Transport: httpsig.NewSignTransport(http.DefaultTransport, httpsig.WithHmacSha256("key1", []byte(secret))), } resp, err := client.Get("http://127.0.0.1:1234/") if err != nil { fmt.Println("got err: ", err) return } defer resp.Body.Close() fmt.Println(resp.Status) }
Output: 200 OK
Index ¶
- Constants
- func NewSignTransport(transport http.RoundTripper, opts ...signOption) http.RoundTripper
- func NewVerifyMiddleware(opts ...verifyOption) func(http.Handler) http.Handler
- func WithDigestAlgorithms(algorithms ...DigestAlgorithm) digestOption
- func WithHmacSha256(keyID string, secret []byte) signOrVerifyOption
- func WithSignEcdsaP256Sha256(keyID string, pk *ecdsa.PrivateKey) signOption
- func WithSignEcdsaP384Sha384(keyID string, pk *ecdsa.PrivateKey) signOption
- func WithSignEd25519(keyID string, pk ed25519.PrivateKey) signOption
- func WithSignFields(fields ...string) signOption
- func WithSignName(name string) signOption
- func WithSignParamValues(params *SignatureParameters) signOption
- func WithSignParams(params ...Param) signOption
- func WithSignRsaPkcs1v15Sha256(keyID string, pk *rsa.PrivateKey) signOption
- func WithSignRsaPssSha512(keyID string, pk *rsa.PrivateKey) signOption
- func WithVerifyAll(all bool) verifyOption
- func WithVerifyEcdsaP256Sha256(keyID string, pk *ecdsa.PublicKey) verifyOption
- func WithVerifyEcdsaP384Sha384(keyID string, pk *ecdsa.PublicKey) verifyOption
- func WithVerifyEd25519(keyID string, pk ed25519.PublicKey) verifyOption
- func WithVerifyMaxAge(d time.Duration) verifyOption
- func WithVerifyNotAfter(t time.Time) verifyOption
- func WithVerifyRequiredFields(fields ...string) verifyOption
- func WithVerifyRequiredParams(params ...string) verifyOption
- func WithVerifyRsaPkcs1v15Sha256(keyID string, pk *rsa.PublicKey) verifyOption
- func WithVerifyRsaPssSha512(keyID string, pk *rsa.PublicKey) verifyOption
- func WithVerifyTolerance(d time.Duration) verifyOption
- func WithVerifyingKeyResolver(resolver VerifyingKeyResolver) verifyOption
- type Algorithm
- type DigestAlgorithm
- type DigestConfig
- type Digestor
- type EcdsaP256SigningKey
- type EcdsaP256VerifyingKey
- type EcdsaP384SigningKey
- type EcdsaP384VerifyingKey
- type Ed25519SigningKey
- type Ed25519VerifyingKey
- type HmacSha256SigningKey
- type HmacSha256VerifyingKey
- type Message
- type Param
- type RsaPkcs1v15Sha256SigningKey
- type RsaPkcs1v15Sha256VerifyingKey
- type RsaPssSha512SigningKey
- type RsaPssSha512VerifyingKey
- type SignConfig
- type SignatureParameters
- type Signer
- type SigningKey
- type Verifier
- type VerifyConfig
- type VerifyingKey
- type VerifyingKeyResolver
Examples ¶
Constants ¶
const ( SignatureHeader = "Signature" SignatureInputHeader = "Signature-Input" ContentDigestHeader = "Content-Digest" )
Variables ¶
This section is empty.
Functions ¶
func NewSignTransport ¶
func NewSignTransport(transport http.RoundTripper, opts ...signOption) http.RoundTripper
NewSignTransport returns a new client transport that wraps the provided transport with http message signing and body digest creation.
Use the various `WithSign*` option funcs to configure signature algorithms with their provided key ids. You must provide at least one signing option. A signature for every provided key id is included on each request. Multiple included signatures allow you to gracefully introduce stronger algorithms, rotate keys, etc.
func NewVerifyMiddleware ¶
NewVerifyMiddleware returns a configured http server middleware that can be used to wrap multiple handlers for http message signature and digest verification.
Use the `WithVerify*` option funcs to configure signature verification algorithms and verification parameters.
Requests with missing signatures, malformed signature headers, expired signatures, or invalid signatures are rejected with a `400` response. Only one valid signature is required from the known key ids by default.
func WithDigestAlgorithms ¶ added in v0.4.0
func WithDigestAlgorithms(algorithms ...DigestAlgorithm) digestOption
WithDigestAlgorithms sets the digest algorithms to use for signing or signature verification. default: sha-256
func WithHmacSha256 ¶
WithHmacSha256 adds signing or signature verification using `hmac-sha256` with the given shared secret using the given key id.
func WithSignEcdsaP256Sha256 ¶
func WithSignEcdsaP256Sha256(keyID string, pk *ecdsa.PrivateKey) signOption
WithSignEcdsaP256Sha256 adds signing using `ecdsa-p256-sha256` with the given private key using the given key id.
func WithSignEcdsaP384Sha384 ¶
func WithSignEcdsaP384Sha384(keyID string, pk *ecdsa.PrivateKey) signOption
WithSignEcdsaP384Sha384 adds signing using `ecdsa-p384-sha384` with the given private key using the given key id.
func WithSignEd25519 ¶
func WithSignEd25519(keyID string, pk ed25519.PrivateKey) signOption
WithSignEd25519 adds signing using `ed25519` with the given private key using the given key id.
func WithSignFields ¶ added in v0.4.0
func WithSignFields(fields ...string) signOption
WithSignFields sets the HTTP fields / derived component names to be included in signing. default: none
func WithSignName ¶ added in v0.4.0
func WithSignName(name string) signOption
WithSignName sets the name of the signature to be used for signing. default: "sig"
func WithSignParamValues ¶ added in v0.4.0
func WithSignParamValues(params *SignatureParameters) signOption
WithSignParamValues sets the signature parameters to be included in signing.
func WithSignParams ¶ added in v0.4.0
func WithSignParams(params ...Param) signOption
WithSignParams sets the signature parameters to be included in signing. default: created, keyid, alg
func WithSignRsaPkcs1v15Sha256 ¶
func WithSignRsaPkcs1v15Sha256(keyID string, pk *rsa.PrivateKey) signOption
WithSignRsaPkcs1v15Sha256 adds signing using `rsa-v1_5-sha256` with the given private key using the given key id.
func WithSignRsaPssSha512 ¶
func WithSignRsaPssSha512(keyID string, pk *rsa.PrivateKey) signOption
WithSignRsaPssSha512 adds signing using `rsa-pss-sha512` with the given private key using the given key id.
func WithVerifyAll ¶ added in v0.4.0
func WithVerifyAll(all bool) verifyOption
WithVerifyAll sets whether all signatures must be valid. default: false
func WithVerifyEcdsaP256Sha256 ¶
WithVerifyEcdsaP256Sha256 adds signature verification using `ecdsa-p256-sha256` with the given public key using the given key id.
func WithVerifyEcdsaP384Sha384 ¶
WithVerifyEcdsaP384Sha384 adds signature verification using `ecdsa-p384-sha384` with the given public key using the given key id.
func WithVerifyEd25519 ¶
WithVerifyEd25519 adds signature verification using `ed25519` with the given public key using the given key id.
func WithVerifyMaxAge ¶ added in v0.4.0
WithVerifyMaxAge sets the maximum age of a signature. default: 0
func WithVerifyNotAfter ¶ added in v0.4.0
WithVerifyNotAfter sets the time after which signatures are considered expired. default: time.Now() + 5 mins
func WithVerifyRequiredFields ¶ added in v0.4.0
func WithVerifyRequiredFields(fields ...string) verifyOption
WithVerifyRequiredFields sets the required HTTP fields / derived component names. default: []
func WithVerifyRequiredParams ¶ added in v0.4.0
func WithVerifyRequiredParams(params ...string) verifyOption
WithVerifyRequiredParams sets the required signature parameters. default: []
func WithVerifyRsaPkcs1v15Sha256 ¶
WithVerifyRsaPkcs1v15Sha256 adds signature verification using `rsa-v1_5-sha256` with the given public key using the given key id.
func WithVerifyRsaPssSha512 ¶
WithVerifyRsaPssSha512 adds signature verification using `rsa-pss-sha512` with the given public key using the given key id.
func WithVerifyTolerance ¶ added in v0.4.0
WithVerifyTolerance sets the clock tolerance for verifying created and expires times. default: 0
func WithVerifyingKeyResolver ¶
func WithVerifyingKeyResolver(resolver VerifyingKeyResolver) verifyOption
WithVerifyingKeyResolver sets the resolver to use for verifying keys.
Types ¶
type Algorithm ¶ added in v0.3.0
type Algorithm string
Algorithm is the signature algorithm to use. Available algorithms are: - RSASSA-PKCS1-v1_5 using SHA-256 (rsa-v1_5-sha256) - RSASSA-PSS using SHA-512 (rsa-pss-sha512) - ECDSA using curve P-256 DSS and SHA-256 (ecdsa-p256-sha256) - ECDSA using curve P-384 DSS and SHA-384 (ecdsa-p384-sha384) - EdDSA using curve edwards25519 (ed25519) - HMAC using SHA-256 (hmac-sha256)
const ( AlgorithmRsaPkcs1v15Sha256 Algorithm = "rsa-v1_5-sha256" AlgorithmRsaPssSha512 Algorithm = "rsa-pss-sha512" AlgorithmEcdsaP256Sha256 Algorithm = "ecdsa-p256-sha256" AlgorithmEcdsaP384Sha384 Algorithm = "ecdsa-p384-sha384" AlgorithmEd25519 Algorithm = "ed25519" AlgorithmHmacSha256 Algorithm = "hmac-sha256" )
type DigestAlgorithm ¶ added in v0.4.0
type DigestAlgorithm string
DigestAlgorithm is the digest algorithm to use. Available algorithms are: - SHA-256 (sha-256) - SHA-512 (sha-512)
const ( DigestAlgorithmSha256 DigestAlgorithm = "sha-256" DigestAlgorithmSha512 DigestAlgorithm = "sha-512" )
type DigestConfig ¶ added in v0.4.0
type DigestConfig struct { // List of digest algorithms to use when creating a digest header. // default: sha-256 Algorithms []DigestAlgorithm }
type Digestor ¶ added in v0.4.0
type Digestor struct {
// contains filtered or unexported fields
}
func NewDigestor ¶ added in v0.4.0
func NewDigestor(opts ...digestOption) *Digestor
NewDigestor creates a new digestor with the given options
type EcdsaP256SigningKey ¶ added in v0.3.0
type EcdsaP256SigningKey struct { *ecdsa.PrivateKey KeyID string }
func (*EcdsaP256SigningKey) GetAlgorithm ¶ added in v0.4.0
func (k *EcdsaP256SigningKey) GetAlgorithm() Algorithm
func (*EcdsaP256SigningKey) GetKeyID ¶ added in v0.4.0
func (k *EcdsaP256SigningKey) GetKeyID() string
type EcdsaP256VerifyingKey ¶ added in v0.3.0
func (*EcdsaP256VerifyingKey) GetAlgorithm ¶ added in v0.4.0
func (k *EcdsaP256VerifyingKey) GetAlgorithm() Algorithm
func (*EcdsaP256VerifyingKey) GetKeyID ¶ added in v0.4.0
func (k *EcdsaP256VerifyingKey) GetKeyID() string
type EcdsaP384SigningKey ¶ added in v0.3.0
type EcdsaP384SigningKey struct { *ecdsa.PrivateKey KeyID string }
func (*EcdsaP384SigningKey) GetAlgorithm ¶ added in v0.4.0
func (k *EcdsaP384SigningKey) GetAlgorithm() Algorithm
func (*EcdsaP384SigningKey) GetKeyID ¶ added in v0.4.0
func (k *EcdsaP384SigningKey) GetKeyID() string
type EcdsaP384VerifyingKey ¶ added in v0.3.0
func (*EcdsaP384VerifyingKey) GetAlgorithm ¶ added in v0.4.0
func (k *EcdsaP384VerifyingKey) GetAlgorithm() Algorithm
func (*EcdsaP384VerifyingKey) GetKeyID ¶ added in v0.4.0
func (k *EcdsaP384VerifyingKey) GetKeyID() string
type Ed25519SigningKey ¶ added in v0.3.0
type Ed25519SigningKey struct { ed25519.PrivateKey KeyID string }
func (*Ed25519SigningKey) GetAlgorithm ¶ added in v0.4.0
func (k *Ed25519SigningKey) GetAlgorithm() Algorithm
func (*Ed25519SigningKey) GetKeyID ¶ added in v0.4.0
func (k *Ed25519SigningKey) GetKeyID() string
type Ed25519VerifyingKey ¶ added in v0.3.0
func (*Ed25519VerifyingKey) GetAlgorithm ¶ added in v0.4.0
func (k *Ed25519VerifyingKey) GetAlgorithm() Algorithm
func (*Ed25519VerifyingKey) GetKeyID ¶ added in v0.4.0
func (k *Ed25519VerifyingKey) GetKeyID() string
type HmacSha256SigningKey ¶ added in v0.3.0
func (*HmacSha256SigningKey) GetAlgorithm ¶ added in v0.4.0
func (k *HmacSha256SigningKey) GetAlgorithm() Algorithm
func (*HmacSha256SigningKey) GetKeyID ¶ added in v0.4.0
func (k *HmacSha256SigningKey) GetKeyID() string
type HmacSha256VerifyingKey ¶ added in v0.3.0
func (*HmacSha256VerifyingKey) GetAlgorithm ¶ added in v0.4.0
func (k *HmacSha256VerifyingKey) GetAlgorithm() Algorithm
func (*HmacSha256VerifyingKey) GetKeyID ¶ added in v0.4.0
func (k *HmacSha256VerifyingKey) GetKeyID() string
type Message ¶ added in v0.4.0
type Message struct { Method string Authority string URL *url.URL Header http.Header StatusCode int RequestHeader *http.Header IsRequest bool Context context.Context }
message is a minimal representation of an HTTP request or response, containing the values needed to construct a signature.
func MessageFromRequest ¶ added in v0.4.0
func MessageFromResponse ¶ added in v0.4.0
type RsaPkcs1v15Sha256SigningKey ¶ added in v0.3.0
type RsaPkcs1v15Sha256SigningKey struct { *rsa.PrivateKey KeyID string }
func (*RsaPkcs1v15Sha256SigningKey) GetAlgorithm ¶ added in v0.4.0
func (k *RsaPkcs1v15Sha256SigningKey) GetAlgorithm() Algorithm
func (*RsaPkcs1v15Sha256SigningKey) GetKeyID ¶ added in v0.4.0
func (k *RsaPkcs1v15Sha256SigningKey) GetKeyID() string
type RsaPkcs1v15Sha256VerifyingKey ¶ added in v0.3.0
func (*RsaPkcs1v15Sha256VerifyingKey) GetAlgorithm ¶ added in v0.4.0
func (k *RsaPkcs1v15Sha256VerifyingKey) GetAlgorithm() Algorithm
func (*RsaPkcs1v15Sha256VerifyingKey) GetKeyID ¶ added in v0.4.0
func (k *RsaPkcs1v15Sha256VerifyingKey) GetKeyID() string
type RsaPssSha512SigningKey ¶ added in v0.3.0
type RsaPssSha512SigningKey struct { *rsa.PrivateKey KeyID string }
func (*RsaPssSha512SigningKey) GetAlgorithm ¶ added in v0.4.0
func (k *RsaPssSha512SigningKey) GetAlgorithm() Algorithm
func (*RsaPssSha512SigningKey) GetKeyID ¶ added in v0.4.0
func (k *RsaPssSha512SigningKey) GetKeyID() string
type RsaPssSha512VerifyingKey ¶ added in v0.3.0
func (*RsaPssSha512VerifyingKey) GetAlgorithm ¶ added in v0.4.0
func (k *RsaPssSha512VerifyingKey) GetAlgorithm() Algorithm
func (*RsaPssSha512VerifyingKey) GetKeyID ¶ added in v0.4.0
func (k *RsaPssSha512VerifyingKey) GetKeyID() string
type SignConfig ¶ added in v0.4.0
type SignConfig struct { // The key to use for signing Key SigningKey // The name to try to use for the signature // Default: 'sig' Name *string // The parameters to add to the signature // Default: see defaultParams Params []Param // The HTTP fields / derived component names to sign // Default: none Fields []string // Specified parameter values to use (eg: created time, expires time, etc) // This can be used by consumers to override the default expiration time or explicitly opt-out // of adding creation time (by setting `created: nil`) ParamValues *SignatureParameters }
SignConfig is the configuration for a signer
type SignatureParameters ¶ added in v0.4.0
type SignatureParameters struct { // The created time for the signature. `nil` indicates not to populate the `created` time // default: time.Now() Created *time.Time // The time the signature should be deemed to have expired // default: time.Now() + 5 mins Expires *time.Time // A nonce for the request Nonce *string // The algorithm the signature is signed with (overrides the alg provided by the signing key) Alg *Algorithm // The key id the signature is signed with (overrides the keyid provided by the signing key) KeyID *string // A tag parameter for the signature Tag *string }
The signature parameters to include in signing
type Signer ¶
type Signer struct {
// contains filtered or unexported fields
}
type SigningKey ¶ added in v0.3.0
type SigningKey interface { Sign(data []byte) ([]byte, error) GetKeyID() string GetAlgorithm() Algorithm }
The key to use for signing
type Verifier ¶
type Verifier struct {
// contains filtered or unexported fields
}
func NewVerifier ¶
func NewVerifier(opts ...verifyOption) *Verifier
NewVerifier creates a new verifier with the given options
Use the `WithVerify*` option funcs to configure signature verification algorithms and verification parameters.
type VerifyConfig ¶ added in v0.4.0
type VerifyConfig struct { // The keys to use for signing Keys map[string]VerifyingKey // Resolver for verifying keys KeyResolver VerifyingKeyResolver // A date that the signature can't have been marked as `created` after // Default: time.Now() + tolerance NotAfter *time.Time // The maximum age of the signature - this effectively overrides the `expires` value for the // signature (unless the expires age is less than the maxAge specified) if provided MaxAge *time.Duration // A clock tolerance when verifying created/expires times // Default: 0 Tolerance *time.Duration // Any parameters that *must* be in the signature (eg: require a created time) // Default: [] RequiredParams []string // Any fields that *must* be in the signature (eg: Authorization, Digest, etc) // Default: [] RequiredFields []string // Verify every signature in the request. By default, only 1 signature will need to be valid // for the verification to pass. // Default: false All bool }
VerifyConfig is the configuration for a verifier
type VerifyingKey ¶
type VerifyingKey interface { Verify(data []byte, signature []byte) error GetKeyID() string GetAlgorithm() Algorithm }
VerifyingKey is the key to use for verifying a signature
type VerifyingKeyResolver ¶
type VerifyingKeyResolver interface {
Resolve(ctx context.Context, keyID string) (VerifyingKey, error)
}
VerifyingKeyResolver is used to resolve a key id to a verifying key