Documentation
¶
Overview ¶
Package utils provides crypto and encoding helpers — PEM/PKCS8 key generation and parsing, JWK/JWKS conversion, RFC 7638 kid thumbprints, JWT signing-method lookup, and Flask session-cookie decoding.
<!-- design:start --> This package is a leaf bag of stateless helpers shared across OneAuth. It owns three loosely related concerns. First, asymmetric key plumbing: generating RSA (NIST-floored at MinRSAKeySize=2048) and ECDSA P-256 key pairs, and encoding/parsing them as PKIX public PEM and PKCS8 private PEM. Second, JWK handling per RFC 7517/7638: converting public keys to and from JWK structs (public components only, never private fields), and computing deterministic key IDs as RFC 7638 thumbprints for asymmetric keys or a SHA-256 base64url hash for HMAC secrets. Third, a self-contained Flask session-cookie decoder for interop with a Python backend. It does not store keys, manage rotation, or sign/verify tokens — callers own those.
A few cross-cutting rules: IsAsymmetricAlg is the single gate deciding whether key material is PEM-parsed (RS256/ES256) or passed through raw (HMAC). DecodeVerifyKey is idempotent — already-typed keys pass straight back — and SigningMethodForAlg errors on unknown algorithms rather than silently defaulting to HS256 (empty string is the one allowed HS256 alias). ECDSA encoding uses pub.Bytes() (Go 1.25+) with explicit zero-padding to the curve coordinate length, and JWKToPublicKey validates exponent and coordinate sizes so malformed input errors instead of yielding bad keys.
ENTITIES ¶
MinRSAKeySize — minimum RSA size in bits (2048), enforcing the NIST SP 800-57 floor.
GenerateRSAKeyPair — generates an RSA pair as PEM bytes, rejecting sizes below MinRSAKeySize.
GenerateECDSAKeyPair — generates an ECDSA P-256 pair as PEM bytes (P-256 is the only curve the JWK path supports).
ParsePublicKeyPEM — parses a PKIX public-key PEM into a crypto.PublicKey.
ParsePrivateKeyPEM — parses a PKCS8 private-key PEM (PKCS1/SEC1 not supported).
EncodePublicKeyPEM — encodes a crypto.PublicKey as PKIX "PUBLIC KEY" PEM.
EncodePrivateKeyPEM — encodes a crypto.PrivateKey as PKCS8 "PRIVATE KEY" PEM so one parser handles RSA and ECDSA.
DecodeVerifyKey — normalizes raw KeyStore material into the JWT verify key type for an alg; HMAC passes through, RS256/ES256 PEM-parse, already typed keys are returned as-is.
IsAsymmetricAlg — reports whether an alg is RS256/ES256; the gate between PEM-parse and raw-bytes branches.
SigningMethodForAlg — maps an alg string to a jwt.SigningMethod, erroring on unknown algs; empty string means HS256.
JWK — RFC 7517 JSON Web Key holding only public components, omitting private fields so they cannot leak via JWKS.
JWKSet — RFC 7517 §5 wrapper for a list of JWKs.
PublicKeyToJWK — converts any crypto.PublicKey to a JWK, dispatching on type and erroring on unsupported keys.
RSAPublicKeyToJWK — builds an RSA JWK with use=sig and key_ops=[verify].
ECDSAPublicKeyToJWK — builds an EC JWK using pub.Bytes() (Go 1.25+) with zero-padded coordinates, use=sig, key_ops=[verify].
JWKToPublicKey — reconstructs a crypto.PublicKey and alg from a JWK, validating exponent/coordinate sizes.
ComputeKid — computes a deterministic 43-char kid: RFC 7638 thumbprint for asymmetric keys, SHA-256 for HMAC; []byte under an asymmetric alg is parsed to take the thumbprint path.
StrMap — alias for map[string]any used for decoded Flask payloads.
FlaskAuth — decodes and verifies Flask session cookies from an app secret; LogCookies gates verbose debug logging.
FlaskAuth.NormalizedSecretKey — pads/truncates the secret to 32 bytes and base64-encodes it as a Fernet key, mirroring Flask's derivation quirk.
FlaskAuth.DecodeSessionCookie — decodes a base64 cookie body (optionally zlib-decompressed when prefixed with '.') into a StrMap.
FlaskAuth.DecodeSessionUserId — Fernet-decrypts a user ID into '|'-split parts; '~'-prefixed parts are excel-base-decoded to numbers.
FlaskAuth.ParseSignedCookieValue — composes the two decoders to extract _user_id parts plus the full session map. <!-- design:end -->
Index ¶
- Constants
- func ComputeKid(key any, alg string) (string, error)
- func DecodeVerifyKey(rawKey any, alg string) (any, error)
- func EncodePrivateKeyPEM(priv crypto.PrivateKey) ([]byte, error)
- func EncodePublicKeyPEM(pub crypto.PublicKey) ([]byte, error)
- func GenerateECDSAKeyPair() (privPEM, pubPEM []byte, err error)
- func GenerateRSAKeyPair(bits int) (privPEM, pubPEM []byte, err error)
- func IsAsymmetricAlg(alg string) bool
- func JWKToPublicKey(jwk JWK) (crypto.PublicKey, string, error)
- func ParsePrivateKeyPEM(pemBytes []byte) (crypto.PrivateKey, error)
- func ParsePublicKeyPEM(pemBytes []byte) (crypto.PublicKey, error)
- func SigningMethodForAlg(alg string) (jwt.SigningMethod, error)
- type FlaskAuth
- func (f *FlaskAuth) DecodeSessionCookie(base64value string) (out StrMap, err error)
- func (f *FlaskAuth) DecodeSessionUserId(userid string) (out []interface{})
- func (f *FlaskAuth) NormalizedSecretKey() string
- func (f *FlaskAuth) ParseSignedCookieValue(value string) (parts []interface{}, sessmap StrMap)
- type JWK
- type JWKSet
- type StrMap
Constants ¶
const MinRSAKeySize = 2048
MinRSAKeySize is the minimum allowed RSA key size in bits (NIST SP 800-57).
Variables ¶
This section is empty.
Functions ¶
func ComputeKid ¶ added in v0.0.38
ComputeKid computes a deterministic key ID (kid) for JWT headers. For asymmetric keys, this implements RFC 7638 JWK Thumbprint. For HMAC keys ([]byte), it returns SHA-256 of the raw bytes, base64url-encoded. The result is always 43 characters (256-bit hash, base64url, no padding).
Supported key types:
func DecodeVerifyKey ¶
DecodeVerifyKey converts raw key material from a KeyStore into the appropriate type for JWT verification based on the algorithm.
- For HMAC algorithms (HS256/HS384/HS512): returns the key as-is (expected to be []byte)
- For RS256: if key is []byte, parses as PEM to *rsa.PublicKey; if already *rsa.PublicKey, returns as-is
- For ES256: if key is []byte, parses as PEM to *ecdsa.PublicKey; if already *ecdsa.PublicKey, returns as-is
func EncodePrivateKeyPEM ¶
func EncodePrivateKeyPEM(priv crypto.PrivateKey) ([]byte, error)
EncodePrivateKeyPEM encodes a crypto.PrivateKey to PKCS8 PEM format.
func EncodePublicKeyPEM ¶
EncodePublicKeyPEM encodes a crypto.PublicKey to PEM format.
func GenerateECDSAKeyPair ¶
GenerateECDSAKeyPair generates an ECDSA P-256 key pair and returns PEM-encoded private and public keys.
func GenerateRSAKeyPair ¶
GenerateRSAKeyPair generates an RSA key pair and returns PEM-encoded private and public keys. Rejects key sizes below MinRSAKeySize (2048 bits) per NIST SP 800-57.
func IsAsymmetricAlg ¶
IsAsymmetricAlg returns true if the algorithm uses asymmetric keys (RS256, ES256).
func JWKToPublicKey ¶
JWKToPublicKey converts a JWK back to a crypto.PublicKey and returns the algorithm.
func ParsePrivateKeyPEM ¶
func ParsePrivateKeyPEM(pemBytes []byte) (crypto.PrivateKey, error)
ParsePrivateKeyPEM parses a PEM-encoded private key (RSA or ECDSA, PKCS8 format).
func ParsePublicKeyPEM ¶
ParsePublicKeyPEM parses a PEM-encoded public key (RSA or ECDSA).
func SigningMethodForAlg ¶
func SigningMethodForAlg(alg string) (jwt.SigningMethod, error)
SigningMethodForAlg returns the jwt.SigningMethod for the given algorithm string. Returns an error for unrecognized algorithms instead of silently defaulting to HS256. Empty string is treated as HS256 (default for single-tenant deployments).
Types ¶
type FlaskAuth ¶
func (*FlaskAuth) DecodeSessionCookie ¶
DecodeSessionCookie decodes a Flask session cookie from its base64 representation.
func (*FlaskAuth) DecodeSessionUserId ¶
DecodeSessionUserId decodes a Fernet-encrypted Flask session user ID.
func (*FlaskAuth) NormalizedSecretKey ¶
func (*FlaskAuth) ParseSignedCookieValue ¶
ParseSignedCookieValue decodes a Flask session cookie and extracts the user ID parts.
type JWK ¶
type JWK struct {
Kty string `json:"kty"` // "RSA" or "EC"
Kid string `json:"kid"` // key identifier (RFC 7638 thumbprint)
Alg string `json:"alg"` // "RS256" or "ES256"
Use string `json:"use"` // "sig"
KeyOps []string `json:"key_ops"` // ["verify"] — explicit usage restriction
N string `json:"n,omitempty"` // RSA modulus (base64url, no padding)
E string `json:"e,omitempty"` // RSA exponent (base64url, no padding)
Crv string `json:"crv,omitempty"` // EC curve ("P-256")
X string `json:"x,omitempty"` // EC x-coordinate (base64url, no padding)
Y string `json:"y,omitempty"` // EC y-coordinate (base64url, no padding)
}
JWK represents a JSON Web Key (RFC 7517). Only public key components are included — the struct intentionally omits private key fields (d, p, q, dp, dq, qi) so they cannot leak via JWKS.
func ECDSAPublicKeyToJWK ¶
ECDSAPublicKeyToJWK converts an ECDSA public key to a JWK. Uses pub.Bytes() (Go 1.25+) instead of deprecated X/Y fields.
func PublicKeyToJWK ¶
PublicKeyToJWK converts a crypto.PublicKey to a JWK, dispatching by key type.
type JWKSet ¶
type JWKSet struct {
Keys []JWK `json:"keys"`
}
JWKSet represents a JSON Web Key Set (RFC 7517 Section 5).