Attesto.Key (Attesto v0.5.0)

Copy Markdown View Source

Pure helpers for working with the RSA signing material as PEM strings.

An RSA private key already contains its public half, so there is never a separately stored public PEM to drift out of sync. public_pem/1 derives the public key from a private PEM, giving exactly one source of truth: the verification key always matches the signing key. This closes a real failure mode where a tracked public PEM and a regenerated private key silently mismatch and every verification fails.

kid/1 is the RFC 7638 JWK thumbprint of a key's public half. It is stable for a given key and changes iff the key changes, so rotating to a new key yields a distinct kid automatically - no separate identifier to assign or track.

Summary

Functions

Parse a PEM (private or public) into a JOSE.JWK.

The RFC 7638 SHA-256 JWK thumbprint (kid) of the public half of the key in pem. Accepts a private or public PEM; both yield the same thumbprint because it is computed over the public members only.

Derive the public key, in conventional SPKI (-----BEGIN PUBLIC KEY-----) PEM form, from a private RSA key PEM.

Parse a private PEM into a JOSE.JWK whose public half can sign and derive a kid.

Functions

jwk(pem)

@spec jwk(String.t()) :: JOSE.JWK.t()

Parse a PEM (private or public) into a JOSE.JWK.

Raises ArgumentError if pem does not contain exactly one parseable key. JOSE.JWK.from_pem/1 returns [] for input with no key entry and a list for a multi-key PEM; left unguarded, thumbprint/1 of those returns [] rather than a string, which would silently poison kid/1 and verification-key selection. Failing loudly here surfaces a malformed keystore PEM as a configuration error instead of a request-time mystery.

Also raises if the key is not RSA. Attesto signs and verifies RS256 exclusively, so an EC (or any non-RSA) key has no valid role as a signing or verification key. Rejecting it here prevents two failure modes: a JWKS that advertises an EC key mislabelled alg: "RS256" (Attesto.JWKS), and an EC signing key that would otherwise crash deep inside JOSE at mint time instead of failing as a clear configuration error.

kid(pem)

@spec kid(String.t()) :: String.t()

The RFC 7638 SHA-256 JWK thumbprint (kid) of the public half of the key in pem. Accepts a private or public PEM; both yield the same thumbprint because it is computed over the public members only.

public_pem(pem)

@spec public_pem(String.t()) :: String.t()

Derive the public key, in conventional SPKI (-----BEGIN PUBLIC KEY-----) PEM form, from a private RSA key PEM.

Accepts the PKCS#1 (RSA PRIVATE KEY) and PKCS#8 (PRIVATE KEY) forms. Raises ArgumentError - signing material is operator-provided, so a misconfiguration is a deploy-time failure that should be loud rather than silently verifying against garbage - if pem contains no key entry, contains more than one, or contains a non-RSA key (attesto signs RS256; an EC or public-only key cannot be a signing key).

signing_jwk(pem)

@spec signing_jwk(String.t()) :: JOSE.JWK.t()

Parse a private PEM into a JOSE.JWK whose public half can sign and derive a kid.

Unlike jwk/1, this rejects public-only RSA PEMs: they are valid verification material, but cannot sign RS256 tokens.