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