Documentation
¶
Overview ¶
Package hmacsig is the one definition of a webhook HMAC signature: which bytes are signed, how the signature is written into its header, and how a header is read back into the signatures it carries (#1996).
The platform verifies these signatures on its inbound webhook sources (internal/webhook/whauth) and writes them on an outbound connection whose auth_mode is hmac (internal/upstreamauth). Both build on this package, so a connection and a source configured with the same values agree by construction rather than by two implementations being kept in step.
It knows nothing about requests, sources or connections: a caller hands it a Scheme, the secret, the delivery id and timestamp it read or chose, and the body.
Index ¶
- Constants
- Variables
- func PresetNames() []string
- func ValidAlgorithm(a string) bool
- func ValidEncoding(e string) bool
- func ValidFormat(f string) bool
- func ValidSecretEncoding(e string) bool
- func ValidSigned(v string) bool
- type Compiled
- func (c Compiled) Header(secret, id, timestamp string, body []byte) string
- func (c Compiled) MAC(secret, id, timestamp string, body []byte) []byte
- func (c Compiled) Matches(sig Signature, secrets []string, id, timestamp string, body []byte) bool
- func (c Compiled) Parse(value string) (Signature, error)
- func (c Compiled) Template() Template
- func (c Compiled) TimestampInHeader() bool
- func (c Compiled) UsesID() bool
- func (c Compiled) UsesTimestamp() bool
- type Pattern
- type Preset
- type Scheme
- func (s Scheme) Compile() (Compiled, error)
- func (s Scheme) Header(secret, id, timestamp string, body []byte) string
- func (s Scheme) MAC(secret, id, timestamp string, body []byte) []byte
- func (s Scheme) Matches(sig Signature, secrets []string, id, timestamp string, body []byte) bool
- func (s Scheme) Parse(value string) (Signature, error)
- func (s Scheme) Payload(id, timestamp string, body []byte) []byte
- func (s Scheme) UsesID() bool
- func (s Scheme) UsesTimestamp() bool
- type Signature
- type Template
Constants ¶
const ( AlgorithmSHA256 = "sha256" AlgorithmSHA1 = "sha1" AlgorithmSHA512 = "sha512" )
Algorithms a scheme signs with.
const ( EncodingHex = "hex" EncodingBase64 = "base64" )
Encodings a signature is written in.
const ( // SignedBody signs the raw body. SignedBody = "body" // SignedTimestampBody signs the timestamp, a ".", and the raw body, // which is what makes a replayed request with an old timestamp fail // even though its signature once verified. SignedTimestampBody = "timestamp.body" // SignedIDTimestampBody signs the delivery id, a ".", the timestamp, a // ".", and the raw body: the Standard Webhooks form. SignedIDTimestampBody = "id.timestamp.body" )
What a scheme signs.
const ( // FormatPlain writes the prefix and the signature. A header may carry // several, separated by spaces, which is how a sender rotating its // secret signs with both (Standard Webhooks' "v1,<a> v1,<b>"). FormatPlain = "" // FormatStripe writes "t=<timestamp>,v1=<signature>": the timestamp is // in the signature header rather than a header of its own, and the // signed bytes are always the timestamp, a ".", and the body. FormatStripe = "stripe" )
How the signature header is written.
const ( // SecretRaw uses the secret's text as the key. SecretRaw = "" // SecretBase64 uses the bytes the secret's base64 decodes to, as a // Microsoft Teams outgoing webhook's security token is used. SecretBase64 = "base64" )
How a secret is read into the HMAC key.
const ( PresetStandardWebhooks = "standard_webhooks" PresetGitHub = "github" PresetStripe = "stripe" // PresetPlatform is what the platform's own inbound webhook // documentation configures a source with, so a deployment's script can // deliver to another deployment's source with one setting. PresetPlatform = "platform" // The senders #2223 added whose proof is an HMAC. PresetSlack = "slack" PresetZoom = "zoom" PresetTeams = "teams" PresetShopify = "shopify" PresetLinear = "linear" PresetGitLab = "gitlab" PresetJira = "jira" )
Presets by name.
const ( PlaceholderID = "{id}" PlaceholderTimestamp = "{timestamp}" PlaceholderBody = "{body}" )
Placeholders a signed-bytes template names (#2223).
const (
PlaceholderSignature = "{signature}"
)
Placeholders a header pattern names (#2223).
Variables ¶
var ErrMalformed = errors.New("hmacsig: the signature header is malformed")
ErrMalformed is returned for a signature header that cannot be read as the scheme writes one.
var ErrTemplate = errors.New("invalid template")
ErrTemplate is returned for a template or pattern that cannot be compiled.
Functions ¶
func PresetNames ¶ added in v1.152.1
func PresetNames() []string
PresetNames lists the presets LookupPreset knows, in a fixed order.
func ValidAlgorithm ¶
ValidAlgorithm reports whether a is an algorithm a scheme signs with.
func ValidEncoding ¶
ValidEncoding reports whether e is an encoding a signature is written in.
func ValidFormat ¶
ValidFormat reports whether f names a signature header format.
func ValidSecretEncoding ¶ added in v1.152.1
ValidSecretEncoding reports whether e names how a secret is read.
func ValidSigned ¶
ValidSigned reports whether v names what a scheme signs: a named form or a template that compiles.
Types ¶
type Compiled ¶ added in v1.152.1
type Compiled struct {
// contains filtered or unexported fields
}
Compiled is a scheme with its template and header pattern compiled, which is what a source verifies every request with: nothing about the scheme is parsed per request.
func (Compiled) MAC ¶ added in v1.152.1
MAC computes the signature of the payload under secret, writing the signed bytes into the HMAC segment by segment.
func (Compiled) Matches ¶ added in v1.152.1
Matches reports whether any of the signatures is the scheme's signature of the payload under any of the secrets. Every comparison is constant-time.
func (Compiled) Parse ¶ added in v1.152.1
Parse reads a signature header's value. A value none of whose signatures can be read is ErrMalformed.
func (Compiled) TimestampInHeader ¶ added in v1.152.1
TimestampInHeader reports whether the signature header carries the timestamp: the Stripe format, or a pattern naming {timestamp}.
func (Compiled) UsesID ¶ added in v1.152.1
UsesID reports whether the signed bytes include a delivery id.
func (Compiled) UsesTimestamp ¶ added in v1.152.1
UsesTimestamp reports whether the signed bytes include a timestamp.
type Pattern ¶ added in v1.152.1
type Pattern struct {
// contains filtered or unexported fields
}
Pattern is a signature header's layout, compiled from text such as "{timestamp}|{signature}" (#2223). It is read by cutting the value at the pattern's literal separators; no regular expression runs.
func CompilePattern ¶ added in v1.152.1
CompilePattern reads a header pattern. {signature} is required and {timestamp} optional; no other placeholder is allowed, neither may repeat, and two placeholders need literal text between them so a value can be cut.
func (Pattern) Read ¶ added in v1.152.1
Read cuts a header value into its signature and timestamp, and reports false for a value that does not have the pattern's layout.
func (Pattern) UsesTimestamp ¶ added in v1.152.1
UsesTimestamp reports whether the header carries the timestamp.
type Preset ¶
Preset names a sender's whole signing convention in one setting.
func LookupPreset ¶
LookupPreset returns the named convention.
type Scheme ¶
type Scheme struct {
Algorithm string
Encoding string
Prefix string
// Signed is a named form (body, timestamp.body, id.timestamp.body) or a
// template over {id}, {timestamp} and {body} (#2223).
Signed string
Format string
// HeaderPattern lays the signature header out over {signature} and
// {timestamp}, in place of a prefix or a format (#2223).
HeaderPattern string
// SecretEncoding is how the secret is read: raw text, or base64.
SecretEncoding string
}
Scheme is how one sender signs.
func (Scheme) Compile ¶ added in v1.152.1
Compile compiles the scheme. A Stripe-format scheme always signs the timestamp, a ".", and the body.
func (Scheme) Matches ¶
Matches reports whether any of the signatures is the scheme's signature of the payload under any of the secrets. Every comparison is constant-time.
func (Scheme) Parse ¶
Parse reads a signature header's value. A value none of whose signatures can be read is ErrMalformed.
func (Scheme) UsesTimestamp ¶
UsesTimestamp reports whether the signed bytes include a timestamp.
type Signature ¶
Signature is what a signature header carries: the signatures, decoded, and, for a format that writes it there, the timestamp.
type Template ¶ added in v1.152.1
type Template struct {
// contains filtered or unexported fields
}
Template is the bytes a scheme signs, compiled from text such as "v0:{timestamp}:{body}" into literal and placeholder segments. Nothing about it is parsed per request.
func CompileTemplate ¶ added in v1.152.1
CompileTemplate reads a signed-bytes template, or one of the named forms body, timestamp.body and id.timestamp.body. {body} is required, since a signature that does not cover the body proves nothing about it; each placeholder appears at most once.
func (Template) Bytes ¶ added in v1.152.1
Bytes is the signed bytes as one slice, for a verifier that needs the whole message rather than a stream (Ed25519).
func (Template) Hash ¶ added in v1.152.1
Hash writes the signed bytes into h, so the body is never copied to put text in front of it. The text around the body is gathered into one buffer, allocated once per call and reused after the body, rather than written a segment at a time: a short write of a string to a hash copies it. It takes a hash.Hash rather than an io.Writer: the id and timestamp are a request's headers, and they go into a MAC, never to a response.
func (Template) String ¶ added in v1.152.1
String is the template as text, the named forms written out.
func (Template) UsesID ¶ added in v1.152.1
UsesID reports whether the signed bytes include the delivery id.
func (Template) UsesTimestamp ¶ added in v1.152.1
UsesTimestamp reports whether the signed bytes include the timestamp.