utils

package
v0.0.84 Latest Latest
Warning

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

Go to latest
Published: May 22, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

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

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

func ComputeKid(key any, alg string) (string, error)

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:

  • []byte: SHA-256 of raw bytes (HS256/HS384/HS512)
  • *rsa.PublicKey or *rsa.PrivateKey: RFC 7638 thumbprint with {"e","kty","n"}
  • *ecdsa.PublicKey or *ecdsa.PrivateKey: RFC 7638 thumbprint with {"crv","kty","x","y"}

func DecodeVerifyKey

func DecodeVerifyKey(rawKey any, alg string) (any, error)

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

func EncodePublicKeyPEM(pub crypto.PublicKey) ([]byte, error)

EncodePublicKeyPEM encodes a crypto.PublicKey to PEM format.

func GenerateECDSAKeyPair

func GenerateECDSAKeyPair() (privPEM, pubPEM []byte, err error)

GenerateECDSAKeyPair generates an ECDSA P-256 key pair and returns PEM-encoded private and public keys.

func GenerateRSAKeyPair

func GenerateRSAKeyPair(bits int) (privPEM, pubPEM []byte, err error)

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

func IsAsymmetricAlg(alg string) bool

IsAsymmetricAlg returns true if the algorithm uses asymmetric keys (RS256, ES256).

func JWKToPublicKey

func JWKToPublicKey(jwk JWK) (crypto.PublicKey, string, error)

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

func ParsePublicKeyPEM(pemBytes []byte) (crypto.PublicKey, error)

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

type FlaskAuth struct {
	AppSecretKey string
	LogCookies   bool
}

func (*FlaskAuth) DecodeSessionCookie

func (f *FlaskAuth) DecodeSessionCookie(base64value string) (out StrMap, err error)

DecodeSessionCookie decodes a Flask session cookie from its base64 representation.

func (*FlaskAuth) DecodeSessionUserId

func (f *FlaskAuth) DecodeSessionUserId(userid string) (out []interface{})

DecodeSessionUserId decodes a Fernet-encrypted Flask session user ID.

func (*FlaskAuth) NormalizedSecretKey

func (f *FlaskAuth) NormalizedSecretKey() string

func (*FlaskAuth) ParseSignedCookieValue

func (f *FlaskAuth) ParseSignedCookieValue(value string) (parts []interface{}, sessmap StrMap)

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

func ECDSAPublicKeyToJWK(kid, alg string, pub *ecdsa.PublicKey) JWK

ECDSAPublicKeyToJWK converts an ECDSA public key to a JWK. Uses pub.Bytes() (Go 1.25+) instead of deprecated X/Y fields.

func PublicKeyToJWK

func PublicKeyToJWK(kid, alg string, pub crypto.PublicKey) (JWK, error)

PublicKeyToJWK converts a crypto.PublicKey to a JWK, dispatching by key type.

func RSAPublicKeyToJWK

func RSAPublicKeyToJWK(kid, alg string, pub *rsa.PublicKey) JWK

RSAPublicKeyToJWK converts an RSA public key to a JWK.

type JWKSet

type JWKSet struct {
	Keys []JWK `json:"keys"`
}

JWKSet represents a JSON Web Key Set (RFC 7517 Section 5).

type StrMap

type StrMap = map[string]any

StrMap is a convenience alias for map[string]any.

Jump to

Keyboard shortcuts

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