httpsig

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 25, 2026 License: AGPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package httpsig signs and verifies amber-store remote-protocol HTTP messages. A request signature covers a canonical CBOR map of {method, path+query, timestamp, nonce, blake3(body)}; a response signature covers {request nonce, status, blake3(body)}. Both are SSHSIG blobs in the amber-store-http namespace, base64 in Amber-* headers. The expensive part — hashing a multi-megabyte body — is blake3; SSHSIG's internal SHA-512 only covers the ~100-byte canonical payload.

Index

Constants

View Source
const (
	HeaderPublicKey = "Amber-Public-Key" // signer's public key, SSH wire format, base64
	HeaderTimestamp = "Amber-Timestamp"  // ns since the Unix epoch, decimal
	HeaderNonce     = "Amber-Nonce"      // random bytes, base64
	HeaderSignature = "Amber-Signature"  // raw SSHSIG blob, base64
)

Header names of the four signature components.

View Source
const DefaultWindow = 5 * time.Minute

DefaultWindow is the default timestamp validity window (each side of now).

View Source
const Namespace = "amber-store-http"

Namespace is the SSHSIG namespace for amber-store HTTP signatures.

Variables

This section is empty.

Functions

func AppendSignatureTrailer

func AppendSignatureTrailer(w io.Writer, sigB64 string) error

AppendSignatureTrailer writes an in-band response signature after an already-written body: the base64 signature followed by its big-endian uint32 length. Unlike an HTTP trailer (which proxies routinely drop) it is part of the body, so it survives any intermediary; unlike a header it can be emitted after a streamed body, when the body hash is finally known. SplitSignatureTrailer recovers it. The signature itself still covers {nonce, status, blake3(prefix)} via SignResponse, so a tampered or truncated prefix fails verification.

func HashBody

func HashBody(body []byte) []byte

HashBody returns the blake3-256 hash of body.

func SignRequest

func SignRequest(req *http.Request, signer ssh.Signer, timestamp int64, nonce, body []byte) error

SignRequest signs req's method, path+query, timestamp, nonce and body, and sets the four Amber-* headers. body must be the exact bytes the request will send.

func SignRequestHash

func SignRequestHash(req *http.Request, signer ssh.Signer, timestamp int64, nonce, bodyHash []byte) error

SignRequestHash is SignRequest for a body the caller has already hashed — needed when the body is streamed (so it is never held whole), since the signature header must be set before the body is sent. bodyHash must be the blake3-256 of the exact bytes the request will send.

func SignResponse

func SignResponse(signer ssh.Signer, nonce []byte, status int, bodyHash []byte) (string, error)

SignResponse signs {nonce, status, bodyHash} with the server identity, returning the base64 header/trailer value. nonce is the request's nonce, binding the response to its request.

func SplitSignatureTrailer

func SplitSignatureTrailer(body []byte) (prefix []byte, sigB64 string, ok bool)

SplitSignatureTrailer splits a fully-buffered body into the signed prefix and the base64 signature appended by AppendSignatureTrailer. ok is false if the body is too short or its trailing length is inconsistent — both of which then fail closed at signature verification.

func VerifyRequest

func VerifyRequest(r *http.Request, body []byte, now time.Time, window time.Duration) (ssh.PublicKey, []byte, error)

VerifyRequest checks r's Amber-* headers against body. See VerifyRequestHash.

func VerifyRequestHash

func VerifyRequestHash(r *http.Request, bodyHash []byte, now time.Time, window time.Duration) (ssh.PublicKey, []byte, error)

VerifyRequestHash is VerifyRequest for callers that have already hashed the body (e.g. a streaming receiver). bodyHash must be blake3-256 of the exact request body bytes: the timestamp must be within window of now and the signature must verify over the reconstructed payload with the claimed public key. It returns the claimed key and the nonce; the caller still must check the nonce for replay and the key against an allowlist. Callers should map any non-nil error to a 401 response. The nonce is returned even on failure so error responses can be signed over it.

func VerifyResponse

func VerifyResponse(serverPubWire, nonce []byte, status int, bodyHash []byte, sigB64 string) error

VerifyResponse checks a response signature against the pinned server key (SSH wire format), the request nonce, the response status and body hash.

Types

This section is empty.

Jump to

Keyboard shortcuts

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