Help us shape the future of Go! Take the 2026 Go Developer Survey

hmacsig

package
v1.152.3 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

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

View Source
const (
	AlgorithmSHA256 = "sha256"
	AlgorithmSHA1   = "sha1"
	AlgorithmSHA512 = "sha512"
)

Algorithms a scheme signs with.

View Source
const (
	EncodingHex    = "hex"
	EncodingBase64 = "base64"
)

Encodings a signature is written in.

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
const (
	PlaceholderID        = "{id}"
	PlaceholderTimestamp = "{timestamp}"
	PlaceholderBody      = "{body}"
)

Placeholders a signed-bytes template names (#2223).

View Source
const (
	PlaceholderSignature = "{signature}"
)

Placeholders a header pattern names (#2223).

Variables

View Source
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.

View Source
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

func ValidAlgorithm(a string) bool

ValidAlgorithm reports whether a is an algorithm a scheme signs with.

func ValidEncoding

func ValidEncoding(e string) bool

ValidEncoding reports whether e is an encoding a signature is written in.

func ValidFormat

func ValidFormat(f string) bool

ValidFormat reports whether f names a signature header format.

func ValidSecretEncoding added in v1.152.1

func ValidSecretEncoding(e string) bool

ValidSecretEncoding reports whether e names how a secret is read.

func ValidSigned

func ValidSigned(v string) bool

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) Header added in v1.152.1

func (c Compiled) Header(secret, id, timestamp string, body []byte) string

Header is the signature header's value for one request.

func (Compiled) MAC added in v1.152.1

func (c Compiled) MAC(secret, id, timestamp string, body []byte) []byte

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

func (c Compiled) Matches(sig Signature, secrets []string, id, timestamp string, body []byte) bool

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

func (c Compiled) Parse(value string) (Signature, error)

Parse reads a signature header's value. A value none of whose signatures can be read is ErrMalformed.

func (Compiled) Template added in v1.152.1

func (c Compiled) Template() Template

Template is the signed bytes' template.

func (Compiled) TimestampInHeader added in v1.152.1

func (c Compiled) TimestampInHeader() bool

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

func (c Compiled) UsesID() bool

UsesID reports whether the signed bytes include a delivery id.

func (Compiled) UsesTimestamp added in v1.152.1

func (c Compiled) UsesTimestamp() bool

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

func CompilePattern(text string) (Pattern, error)

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

func (p Pattern) Read(value string) (signature, timestamp string, ok bool)

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

func (p Pattern) UsesTimestamp() bool

UsesTimestamp reports whether the header carries the timestamp.

func (Pattern) Write added in v1.152.1

func (p Pattern) Write(signature, timestamp string) string

Write lays out a header value.

type Preset

type Preset struct {
	Scheme
	SignatureHeader string
	TimestampHeader string
	IDHeader        string
}

Preset names a sender's whole signing convention in one setting.

func LookupPreset

func LookupPreset(name string) (Preset, bool)

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

func (s Scheme) Compile() (Compiled, error)

Compile compiles the scheme. A Stripe-format scheme always signs the timestamp, a ".", and the body.

func (Scheme) Header

func (s Scheme) Header(secret, id, timestamp string, body []byte) string

Header is the signature header's value for one request.

func (Scheme) MAC

func (s Scheme) MAC(secret, id, timestamp string, body []byte) []byte

MAC computes the signature of the payload under secret.

func (Scheme) Matches

func (s Scheme) Matches(sig Signature, secrets []string, id, timestamp string, body []byte) bool

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

func (s Scheme) Parse(value string) (Signature, error)

Parse reads a signature header's value. A value none of whose signatures can be read is ErrMalformed.

func (Scheme) Payload

func (s Scheme) Payload(id, timestamp string, body []byte) []byte

Payload is the bytes the scheme signs for one request.

func (Scheme) UsesID

func (s Scheme) UsesID() bool

UsesID reports whether the signed bytes include a delivery id.

func (Scheme) UsesTimestamp

func (s Scheme) UsesTimestamp() bool

UsesTimestamp reports whether the signed bytes include a timestamp.

type Signature

type Signature struct {
	MACs      [][]byte
	Timestamp string
}

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

func CompileTemplate(text string) (Template, error)

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

func (t Template) Bytes(id, timestamp string, body []byte) []byte

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

func (t Template) Hash(h hash.Hash, id, timestamp string, body []byte)

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

func (t Template) String() string

String is the template as text, the named forms written out.

func (Template) UsesID added in v1.152.1

func (t Template) UsesID() bool

UsesID reports whether the signed bytes include the delivery id.

func (Template) UsesTimestamp added in v1.152.1

func (t Template) UsesTimestamp() bool

UsesTimestamp reports whether the signed bytes include the timestamp.

Jump to

Keyboard shortcuts

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