jose

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package jose implements the shared JWT/JWS/JWK parsing, encoding and signature-verification primitives used throughout the module: strict parsing, JWK validation, and algorithm-policy enforcement.

It is intentionally low-level and generic — client, server and resource each build role-specific signers/verifiers with their own policy on top of it (see internal/requestobject, internal/jarm, internal/dpop, internal/clientassertion, internal/token). jose itself must not encode any FAPI-specific policy or trust decision; those belong one layer up, where the difference between "signing" and "verifying" — and the resulting trust boundary — is explicit.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMalformed indicates a compact serialization that is not
	// well-formed (wrong number of segments, empty segment, invalid
	// base64url).
	ErrMalformed = errors.New("jose: malformed compact serialization")

	// ErrTooLarge indicates a compact serialization larger than this
	// package is willing to parse.
	ErrTooLarge = errors.New("jose: compact serialization exceeds maximum size")

	// ErrAlgorithmMismatch indicates the algorithm recorded in a JWS
	// header does not match the algorithm the caller required.
	ErrAlgorithmMismatch = errors.New("jose: algorithm mismatch")

	// ErrInvalidSignature indicates a JWS signature that does not
	// verify against the supplied key.
	ErrInvalidSignature = errors.New("jose: invalid signature")

	// ErrPrivateKeyMaterial indicates a JWK contained a private-key
	// component (e.g. "d", "k") where only a public key is acceptable.
	ErrPrivateKeyMaterial = errors.New("jose: jwk contains private key material")
)

Functions

func Sign

func Sign(signer crypto.Signer, header Header, payload []byte) (string, error)

Sign produces a JWS compact serialization: BASE64URL(header) || "." || BASE64URL(payload) || "." || BASE64URL(signature).

If header.JWK is set, it must match signer's public key — Sign refuses to produce a proof that asserts possession of a key other than the one actually used to sign.

Types

type Compact

type Compact struct {
	Header  Header
	Payload []byte
	// contains filtered or unexported fields
}

Compact is a parsed, but not yet signature-verified, JWS compact serialization. Header and Payload must not be trusted until Verify returns nil.

func ParseCompact

func ParseCompact(s string) (Compact, error)

ParseCompact splits and decodes a compact JWS without verifying its signature.

func (Compact) Verify

func (c Compact) Verify(pub crypto.PublicKey, alg fapi.SignatureAlgorithm) error

Verify checks c's signature against pub for exactly alg. It fails if the header's own algorithm does not match alg, so a caller must state which algorithm it expects rather than trusting whatever the header claims — this is what prevents algorithm-confusion attacks.

type Header struct {
	Algorithm fapi.SignatureAlgorithm
	Type      string // "typ", optional
	KeyID     string // "kid", optional
	JWK       *JWK   // "jwk", optional — an embedded public key (used by DPoP)
}

Header is a JWS protected header. Only the members this module's supported operations need are represented, but that does not make this a closed allow-list: RFC 7515 §4.2/§4.3 requires any Public or Private Header Parameter Name a recipient doesn't act on (e.g. "x5c", "cty") to be ignored, not rejected — the header is entirely signature-covered, so an unrecognized informational member can't weaken what Verify checks. The one member enforced beyond what's modeled here is "crit" (RFC 7515 §4.1.11): every name it lists must be one this parser actually understands and processes, or parsing fails outright — an issuer marking something critical that this package doesn't act on is exactly the case "crit" exists to catch.

type JWK

type JWK struct {
	// contains filtered or unexported fields
}

JWK is a parsed, validated public key together with the SignatureAlgorithm it is to be used with. There is no exported way to construct one from raw coordinates — only NewJWK (from a crypto.PublicKey the caller already trusts) or ParseJWK (which validates untrusted wire input) can produce one.

func NewJWK

func NewJWK(pub crypto.PublicKey, alg fapi.SignatureAlgorithm) (JWK, error)

NewJWK wraps pub for use with alg. It fails if pub's type or size does not match what alg requires.

func ParseJWK

func ParseJWK(data []byte, alg fapi.SignatureAlgorithm) (JWK, error)

ParseJWK parses and validates a public JWK from untrusted wire data, checking it against alg. It rejects any member indicating private key material (e.g. "d", "k") — a "public" JWK unexpectedly carrying that is either a server bug leaking private keys or actively malicious, not something to tolerate. Every other member this package doesn't act on (e.g. "x5c", "x5u", "x5t", "x5t#S256", "use") is ignored, not rejected: RFC 7517 §4 requires exactly this — "Additional members can be present in the JWK; if not understood by implementations encountering them, they MUST be ignored" — and this package never resolves a key via its certificate chain, so an x5c present alongside otherwise-valid key material changes nothing about which key gets used.

func (JWK) Algorithm

func (k JWK) Algorithm() fapi.SignatureAlgorithm

Algorithm returns the algorithm this key is to be used with.

func (JWK) MarshalJSON

func (k JWK) MarshalJSON() ([]byte, error)

MarshalJSON encodes k as a public-only JWK containing exactly the members required for its key type, plus "kid" if WithKeyID was used.

func (JWK) PublicKey

func (k JWK) PublicKey() crypto.PublicKey

PublicKey returns the wrapped public key.

func (JWK) Thumbprint

func (k JWK) Thumbprint() (Thumbprint, error)

Thumbprint computes the RFC 7638 JWK thumbprint: the SHA-256 digest of the key's required members, serialized with no whitespace and in lexicographic member-name order.

func (JWK) WithKeyID

func (k JWK) WithKeyID(kid string) JWK

WithKeyID returns a copy of k with its "kid" member set to kid, so it appears in MarshalJSON's output. It exists for publishing a key in a JWKS document, where kid lets a verifier choose the right key; a JWK embedded directly in a JWS header (DPoP, request objects) doesn't need this — a kid there, if present, belongs in the surrounding JWS header instead, not duplicated into the embedded key.

type ParsedJWK

type ParsedJWK struct {
	KeyID     string
	Algorithm fapi.SignatureAlgorithm
	PublicKey crypto.PublicKey
}

ParsedJWK is one key from a parsed JWK Set — algorithm and key ID alongside the public key material, before either the client (issuer discovery) or server (client verification) role wraps it in its own role-specific type. Kept intentionally minimal and un-opinionated about role, matching ARCHITECTURE.md's rule against sharing role-level types: this is a wire-format parsing result, not a role's own key abstraction.

func ParseJWKSet

func ParseJWKSet(body []byte) ([]ParsedJWK, error)

ParseJWKSet parses a JWK Set (RFC 7517 §5) into this module's closed algorithm set, skipping any entry whose algorithm isn't supported or whose shape doesn't parse — one malformed or unsupported entry does not invalidate an otherwise usable key set.

type Thumbprint

type Thumbprint [32]byte

Thumbprint is an RFC 7638 JWK thumbprint.

func (Thumbprint) Equal

func (t Thumbprint) Equal(other Thumbprint) bool

Equal reports whether t and other are the same thumbprint.

func (Thumbprint) String

func (t Thumbprint) String() string

String returns the base64url (no padding) encoding of t.

Jump to

Keyboard shortcuts

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