gose/jose/jws_multi
JWS JSON Serialization for multi-signer signing and verification (RFC 7515 Section 7.2.1).
Example
import gleam/json
import gose/algorithm
import gose/jose/jws_multi
import gose/key
import kryptos/ec
import kryptos/eddsa
let payload = <<"hello":utf8>>
let k1 = key.generate_ec(ec.P256)
let k2 = key.generate_eddsa(eddsa.Ed25519)
let assert Ok(body) =
jws_multi.new(payload:)
|> jws_multi.sign(
algorithm.DigitalSignature(algorithm.Ecdsa(algorithm.EcdsaP256)),
key: k1,
)
let assert Ok(body) =
body
|> jws_multi.sign(algorithm.DigitalSignature(algorithm.Eddsa), key: k2)
let multi = jws_multi.assemble(body)
let json_str = jws_multi.serialize_json(multi) |> json.to_string
let assert Ok(parsed) = jws_multi.parse_json(json_str)
let assert Ok(v) =
jws_multi.verifier(
algorithm.DigitalSignature(algorithm.Ecdsa(algorithm.EcdsaP256)),
keys: [k1],
)
let assert Ok(Nil) = jws_multi.verify(v, parsed)
Phantom States
Body(Building) supports payload configuration (with_detached). Calling
sign transitions the body to Body(Signed), which assemble finalizes
into a serializable MultiJws. The type system prevents modifying the
body after any signature has been computed.
Algorithm Pinning
Each verifier is pinned to a single algorithm. The matched signer’s
protected header alg must match the verifier’s expected algorithm.
Types
Outer body for a multi-signer JWS, parameterized by signing state.
pub opaque type Body(state)
A multi-signer JWS message (JSON General Serialization).
pub opaque type MultiJws
Values
pub fn assemble(body: Body(Signed)) -> MultiJws
Finalize a signed body into a serializable multi-signer JWS.
pub fn is_detached(message: MultiJws) -> Bool
Check whether the message was built or parsed with a detached payload.
pub fn new(payload payload: BitArray) -> Body(Building)
Create a new body pinned to the payload all signers will sign.
pub fn parse_json(
json_str: String,
) -> Result(MultiJws, gose.GoseError)
Parse a JWS from JSON General Serialization format. A missing payload
field indicates a detached payload per RFC 7515 Appendix F.
pub fn payload(message: MultiJws) -> BitArray
Return the payload. Returns an empty BitArray for messages parsed with
a detached payload.
pub fn serialize_json(message: MultiJws) -> json.Json
Serialize as JWS JSON General Serialization. For messages built with
with_detached, the payload field is omitted.
pub fn sign(
body: Body(state),
alg alg: algorithm.SigningAlg,
key key: key.Key(String),
) -> Result(Body(Signed), gose.GoseError)
Compute a per-signer JWS signature over the body’s payload and append it
to the body. Transitions the body to Signed state, preventing further
with_* mutations at compile time.
pub fn verifier(
alg: algorithm.SigningAlg,
keys keys: List(key.Key(String)),
) -> Result(Verifier, gose.GoseError)
Build a verifier pinned to a single algorithm and one or more keys.
pub fn verify(
verifier: Verifier,
message: MultiJws,
) -> Result(Nil, gose.GoseError)
Verify the first matching signer’s signature.
Returns InvalidState if the message was parsed with a detached payload;
use verify_detached instead.
pub fn verify_detached(
verifier: Verifier,
message message: MultiJws,
payload payload: BitArray,
) -> Result(Nil, gose.GoseError)
Verify a detached-payload JWS by supplying the payload at verify time.