Documentation
¶
Overview ¶
Package httpsig implements Freizone's per-request signature authentication: every API request is signed by the calling device's Ed25519 identity key instead of carrying a session or password. Public (not internal) because both the server (verification, via internal/auth's Middleware) and any client -- including the mobile app's Go core -- need to build the same canonical string and, for clients, produce the Signature header itself.
Index ¶
- Constants
- func CanonicalString(method, path, rawQuery, timestamp, nonce, keyID string, body []byte) string
- func CanonicalStringFromRequest(r *http.Request, h RequestSignatureHeaders, body []byte) string
- func CanonicalStringWithBodyDigest(method, path, rawQuery, timestamp, nonce, keyID, bodyDigestHex string) string
- func FormatTimestamp(t time.Time) string
- func ParseTimestamp(s string) (time.Time, error)
- func Sign(method, path, rawQuery string, body []byte, keyID string, timestamp time.Time, ...) string
- func Verify(canonical string, signatureB64 string, pubKey ed25519.PublicKey) error
- func WithinSkew(ts, now time.Time, maxSkew time.Duration) bool
- type RequestSignatureHeaders
Constants ¶
const ( HeaderKeyID = "Signature-Key-Id" HeaderTimestamp = "Signature-Timestamp" HeaderNonce = "Signature-Nonce" HeaderSignature = "Signature" )
HTTP headers carrying the signature material. Naming and canonicalization are a cross-repo wire-format contract -- see docs/PROTOCOL.md.
const HeaderBodyDigest = "Blob-Digest"
HeaderBodyDigest carries the hex SHA-256 of the request body, so a large streamed body can be authenticated without buffering it -- see CanonicalStringWithBodyDigest.
Variables ¶
This section is empty.
Functions ¶
func CanonicalString ¶
CanonicalString builds the exact newline-joined byte sequence that gets signed for a request:
METHOD\npath\nrawQuery\ntimestamp\nnonce\nkeyID\nsha256_hex(body)
func CanonicalStringFromRequest ¶
func CanonicalStringFromRequest(r *http.Request, h RequestSignatureHeaders, body []byte) string
CanonicalStringFromRequest builds the canonical string for an incoming request given its already-parsed signature headers and its raw body bytes (the caller is responsible for having read r.Body and restoring it for downstream handlers).
func CanonicalStringWithBodyDigest ¶ added in v0.10.0
func CanonicalStringWithBodyDigest(method, path, rawQuery, timestamp, nonce, keyID, bodyDigestHex string) string
CanonicalStringWithBodyDigest is CanonicalString for a caller that already knows the body's hex SHA-256 and does not want to hold the body itself.
This is what makes the blob transport signable: the canonical string ends in the body hash, which normally means buffering the whole request to authenticate it -- unacceptable for multi-megabyte uploads. Instead the client states the digest in HeaderBodyDigest, the server verifies the signature over that claim *before reading a byte*, and only then streams the body through a hasher to confirm the bytes match what was signed. A forged signature is therefore rejected at zero storage cost, and a body that does not match its signed digest never becomes a stored blob.
func FormatTimestamp ¶
FormatTimestamp renders a time as the decimal Unix-seconds string used in the Signature-Timestamp header.
func ParseTimestamp ¶
ParseTimestamp parses the Signature-Timestamp header value.
func Sign ¶
func Sign(method, path, rawQuery string, body []byte, keyID string, timestamp time.Time, nonce string, priv ed25519.PrivateKey) string
Sign computes the base64-encoded signature for a request, for use by a client (or test code) constructing the Signature header.
Types ¶
type RequestSignatureHeaders ¶
RequestSignatureHeaders holds the parsed values of the four signature headers from an incoming request.
func ParseRequestHeaders ¶
func ParseRequestHeaders(r *http.Request) (RequestSignatureHeaders, error)
ParseRequestHeaders extracts the signature headers from r, returning an error if any are missing.