Documentation
¶
Index ¶
- Constants
- func CanonicalJSON(v any) (string, error)
- func DeriveUserID(publicKeyBase64 string) string
- func ParsePublicKey(base64Key string) (*ecdsa.PublicKey, error)
- func RequireSignature(next http.HandlerFunc) http.HandlerFunc
- func RequireSignedHeader(next http.HandlerFunc) http.HandlerFunc
- func VerifySignature(message, signatureBase64, publicKeyBase64 string) (bool, error)
- func VerifySignedJSON(body []byte) (cleanData map[string]any, pubKeyBase64 string, userID string, err error)
- type AttestationRequest
- type ChallengeConfig
- type ChallengeStore
- type RotationResult
- type SessionConfig
- type SessionManager
- func (sm *SessionManager) CreateSession(w http.ResponseWriter, r *http.Request) (string, error)
- func (sm *SessionManager) RequireAdmin(isAdmin func(string) (bool, error), next http.HandlerFunc) http.HandlerFunc
- func (sm *SessionManager) RequireSession(next http.HandlerFunc) http.HandlerFunc
- func (sm *SessionManager) VerifySession(r *http.Request) (string, error)
Constants ¶
const ( HeaderUserID = "X-User-Id" HeaderPublicKey = "X-Public-Key" )
Variables ¶
This section is empty.
Functions ¶
func CanonicalJSON ¶
func DeriveUserID ¶
DeriveUserID returns hex(SHA-256(publicKeyBase64)) — hashes the base64 string, not raw bytes.
func ParsePublicKey ¶
ParsePublicKey decodes a base64 SPKI DER-encoded ECDSA public key.
func RequireSignature ¶
func RequireSignature(next http.HandlerFunc) http.HandlerFunc
RequireSignature reads the request body, verifies the embedded ECDSA signature, sets X-User-Id and X-Public-Key headers, and replaces r.Body with the stripped (signature-removed) payload. Returns 401 on any failure.
func RequireSignedHeader ¶
func RequireSignedHeader(next http.HandlerFunc) http.HandlerFunc
RequireSignedHeader verifies the X-Cryptid-Auth header, which must contain a base64-encoded signed JSON payload of the form:
{"method":"GET","path":"/api/foo","timestamp":<unix_ms>,"v":1,"signature":{"data":"...","publicKey":"..."}}
The signature covers all fields except "signature" itself. Method and path must match the actual request. Timestamp must be within 60 seconds of now. Sets X-User-Id and X-Public-Key on success. Returns 401 on any failure.
func VerifySignature ¶
VerifySignature verifies an ECDSA P-256 signature in raw r||s format (64 bytes, 32 each). This matches the Web Crypto API's output format.
func VerifySignedJSON ¶
func VerifySignedJSON(body []byte) (cleanData map[string]any, pubKeyBase64 string, userID string, err error)
VerifySignedJSON extracts the signature field from a JSON body, re-canonicalizes the remaining payload, verifies the ECDSA signature, and returns the clean data, public key, and derived userID.
Expected body shape:
{...fields, "signature": {"data": "<base64 r||s>", "publicKey": "<base64 SPKI>"}}
Types ¶
type AttestationRequest ¶
AttestationRequest holds the verified data from a username attestation request.
func ParseAttestation ¶
func ParseAttestation(body []byte) (*AttestationRequest, error)
ParseAttestation verifies a signed attestation request. The body must be a JSON object signed by the user's key, containing a username field.
type ChallengeConfig ¶
type ChallengeConfig struct {
// MaxAge is how long challenges remain valid. Zero defaults to 60s.
MaxAge time.Duration
// MaxStored limits in-memory challenges before cleanup. Zero defaults to 1000.
MaxStored int
}
ChallengeConfig configures the challenge store.
type ChallengeStore ¶
type ChallengeStore struct {
// contains filtered or unexported fields
}
ChallengeStore provides replay-safe single-use challenge generation. Safe for concurrent use.
func NewChallengeStore ¶
func NewChallengeStore(cfg ChallengeConfig) *ChallengeStore
NewChallengeStore returns a ChallengeStore with defaults applied (MaxAge=60s, MaxStored=1000).
func (*ChallengeStore) Consume ¶
func (cs *ChallengeStore) Consume(challenge string) bool
func (*ChallengeStore) NewChallenge ¶
func (cs *ChallengeStore) NewChallenge() (string, error)
type RotationResult ¶
type RotationResult struct {
OldUserID string
NewUserID string
OldPublicKey string
NewPublicKey string
Proof []byte
}
RotationResult holds the verified data from a key rotation request.
func VerifyRotation ¶
func VerifyRotation(body []byte) (*RotationResult, error)
VerifyRotation verifies a signed key rotation request. The body must be a JSON object signed by the old key, containing a newPublicKey field.
type SessionConfig ¶
type SessionConfig struct {
// CookiePrefix is prepended to the cookie name. Empty uses no prefix.
CookiePrefix string
// CookiePath sets the cookie path. Empty defaults to "/".
CookiePath string
// MaxAge sets the session duration. Empty defaults to 24h.
MaxAge time.Duration
// Secure sets the Secure flag on cookies.
Secure bool
}
SessionConfig holds configuration for a SessionManager.
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager creates and verifies stateless signed session cookies.
func NewSessionManager ¶
func NewSessionManager(cfg SessionConfig) *SessionManager
NewSessionManager returns a SessionManager with defaults applied.
func (*SessionManager) CreateSession ¶
func (sm *SessionManager) CreateSession(w http.ResponseWriter, r *http.Request) (string, error)
CreateSession reads a signed JSON body from r, verifies it, checks expiry, and sets an HttpOnly session cookie on w. Returns the derived userID.
func (*SessionManager) RequireAdmin ¶
func (sm *SessionManager) RequireAdmin(isAdmin func(string) (bool, error), next http.HandlerFunc) http.HandlerFunc
RequireAdmin verifies the session cookie, then calls isAdmin. Sets X-User-Id. Returns 401 for bad session, 403 if isAdmin returns false.
func (*SessionManager) RequireSession ¶
func (sm *SessionManager) RequireSession(next http.HandlerFunc) http.HandlerFunc
RequireSession verifies the session cookie and sets X-User-Id. Returns 401 on failure.
func (*SessionManager) VerifySession ¶
func (sm *SessionManager) VerifySession(r *http.Request) (string, error)
VerifySession reads the session cookie from r, decodes it, re-verifies the signature, and checks that the session has not expired. Returns the userID.