Key material for RFC 9421 HTTP Message Signatures.
A key pairs an algorithm from the HTTP Signature Algorithms registry with its public material and, for signing, its private material:
alg | Public material | Private material |
|---|---|---|
"ed25519" | 32-byte public key | 32-byte seed |
"ecdsa-p256-sha256" | 65-byte uncompressed point | 32-byte scalar |
"rsa-pss-sha512" | [e, n] big-endian binaries | [e, n, d] binaries |
new/1 accepts the material as raw bytes, PEM (PUBLIC KEY,
PRIVATE KEY, EC PRIVATE KEY, RSA PRIVATE KEY), a JWK map, or the
:public_key records those PEMs decode to; from_jwk/1 and to_jwk/1
convert to and from the JWK form the
/.well-known/http-message-signatures-directory document uses. The key
identifier defaults to the RFC 7638 JWK thumbprint (thumbprint/1), as
draft-meunier-http-message-signatures-directory requires.
ECDSA signatures use the raw r || s form RFC 9421 §3.3.4 mandates,
and RSA-PSS uses SHA-512 with a 64-byte salt (§3.3.1).
Summary
Functions
Returns the supported algorithm names.
Builds a key from a JWK map (RFC 7517), including the private part when
d is present.
Generates a fresh key pair for an algorithm.
Builds a key from its algorithm and material.
Signs data with the key's private material, returning the raw
signature bytes RFC 9421 §3.3 defines for the algorithm.
Computes the RFC 7638 JWK thumbprint (SHA-256, Base64url) of a key.
Returns the public JWK for a key, with kid and the HTTP signature
alg name as draft-meunier-http-message-signatures-directory §3 requires.
Verifies a raw signature over data with the key's public material.
Types
Functions
@spec algorithms() :: [alg()]
Returns the supported algorithm names.
Examples
iex> X402.HTTPSignature.Key.algorithms()
["ed25519", "ecdsa-p256-sha256", "rsa-pss-sha512"]
Builds a key from a JWK map (RFC 7517), including the private part when
d is present.
The alg member may name the HTTP signature algorithm; when absent it
is inferred from kty/crv. Any kid is kept.
Examples
iex> jwk = %{"kty" => "OKP", "crv" => "Ed25519", "kid" => "test-key-ed25519",
...> "x" => "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs"}
iex> {:ok, key} = X402.HTTPSignature.Key.from_jwk(jwk)
iex> {key.alg, key.kid, key.private}
{"ed25519", "test-key-ed25519", nil}
iex> X402.HTTPSignature.Key.from_jwk(%{"kty" => "oct", "k" => "secret"})
{:error, {:unsupported_algorithm, "oct"}}
Generates a fresh key pair for an algorithm.
Examples
iex> {:ok, key} = X402.HTTPSignature.Key.generate("ecdsa-p256-sha256")
iex> {byte_size(key.public), byte_size(key.private), String.length(key.kid)}
{65, 32, 43}
iex> X402.HTTPSignature.Key.generate("hmac-sha256")
{:error, {:unsupported_algorithm, "hmac-sha256"}}
Builds a key from its algorithm and material.
At least one of :public_key and :private_key is required; the
public material is derived from the private one when omitted.
Options
:alg- Required. The signature algorithm.:kid(String.t/0) - Key identifier; defaults to the JWK thumbprint.:public_key(term/0) - Public material (raw, PEM, JWK, or:public_keyrecord).:private_key(term/0) - Private material (raw, PEM, JWK, or:public_keyrecord).
Examples
iex> seed = :binary.copy(<<7>>, 32)
iex> {:ok, key} = X402.HTTPSignature.Key.new(alg: "ed25519", private_key: seed, kid: "k1")
iex> {key.alg, key.kid, byte_size(key.public), key.private == seed}
{"ed25519", "k1", 32, true}
iex> X402.HTTPSignature.Key.new(alg: "ed25519", public_key: "too short")
{:error, :invalid_key}
iex> X402.HTTPSignature.Key.new(alg: "hmac-sha256", public_key: "x")
{:error, {:unsupported_algorithm, "hmac-sha256"}}
Signs data with the key's private material, returning the raw
signature bytes RFC 9421 §3.3 defines for the algorithm.
Examples
iex> {:ok, key} = X402.HTTPSignature.Key.generate("ed25519")
iex> {:ok, signature} = X402.HTTPSignature.Key.sign(key, "data")
iex> byte_size(signature)
64
iex> {:ok, key} = X402.HTTPSignature.Key.generate("ed25519")
iex> X402.HTTPSignature.Key.sign(%{key | private: nil}, "data")
{:error, :missing_private_key}
Computes the RFC 7638 JWK thumbprint (SHA-256, Base64url) of a key.
Examples
iex> jwk = %{"kty" => "OKP", "crv" => "Ed25519", "x" => "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs"}
iex> {:ok, key} = X402.HTTPSignature.Key.from_jwk(jwk)
iex> X402.HTTPSignature.Key.thumbprint(key)
"poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"
Returns the public JWK for a key, with kid and the HTTP signature
alg name as draft-meunier-http-message-signatures-directory §3 requires.
Examples
iex> jwk = %{"kty" => "OKP", "crv" => "Ed25519", "x" => "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs"}
iex> {:ok, key} = X402.HTTPSignature.Key.from_jwk(jwk)
iex> X402.HTTPSignature.Key.to_jwk(key)
%{
"kty" => "OKP",
"crv" => "Ed25519",
"x" => "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs",
"kid" => "poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U",
"alg" => "ed25519",
"use" => "sig"
}
Verifies a raw signature over data with the key's public material.
Examples
iex> {:ok, key} = X402.HTTPSignature.Key.generate("ecdsa-p256-sha256")
iex> {:ok, signature} = X402.HTTPSignature.Key.sign(key, "data")
iex> X402.HTTPSignature.Key.verify(key, "data", signature)
true
iex> X402.HTTPSignature.Key.verify(key, "other", signature)
false
iex> X402.HTTPSignature.Key.verify(key, "data", "short")
false