gose/jwe

JSON Web Encryption (JWE) - RFC 7516

This module provides encryption functionality using algorithms from RFC 7518: key encryption (RSA-OAEP, ECDH-ES, AES Key Wrap, AES-GCM Key Wrap, PBES2, dir) and content encryption (AES-GCM, AES-CBC-HMAC).

Non-standard extensions are also supported: ChaCha20 Key Wrap (C20PKW, XC20PKW), ECDH-ES+ChaCha20KW, and ChaCha20-Poly1305/XChaCha20-Poly1305 content encryption.

Example

import gose/jwe
import gose/jwa
import gose/jwk

let key = jwk.generate_enc_key(jwa.AesGcm(jwa.Aes256))
let plaintext = <<"hello world":utf8>>

// Create and encrypt a JWE using direct encryption
let assert Ok(encrypted) = jwe.new_direct(jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(key, plaintext)

// Serialize to compact format
let assert Ok(token) = jwe.serialize_compact(encrypted)

// Parse and decrypt with algorithm pinning
let assert Ok(parsed) = jwe.parse_compact(token)
let assert Ok(decryptor) = jwe.key_decryptor(jwa.JweDirect, jwa.AesGcm(jwa.Aes256), [key])
let assert Ok(decrypted) = jwe.decrypt(decryptor, parsed)

Phantom Types

Jwe(state, family, origin) uses three phantom type parameters:

Algorithm Pinning

Algorithm pinning prevents algorithm confusion attacks:

  1. JWK alg metadata: If a key has alg set via jwk.with_alg, the JWE algorithm must match during encryption and decryption.
  2. Decryptor API: jwe.decrypt() with a Decryptor pins both key encryption and content encryption algorithms; mismatches are rejected.
  3. Key type validation: The key type must match the algorithm (RSA for RSA-OAEP, EC for ECDH-ES, etc.).

For strongest security, always set the alg field on keys or use decryptors.

Unprotected Headers

JWE supports unprotected headers at two levels in JSON serialization:

Security Warning: Unprotected headers are NOT integrity protected. They can be modified by an attacker without detection. Security-critical parameters (alg, enc, crit, zip) are rejected and must be integrity protected.

Use with_shared_unprotected and with_unprotected to add headers during creation. Use decode_shared_unprotected_header and decode_unprotected_header to read parsed headers.

Critical Header Support

The crit header is validated per RFC 7516:

Key Metadata

JWK metadata (use, key_ops) is enforced during encryption and decryption. Keys with incompatible metadata are rejected.

Compression Not Supported

The zip header (DEFLATE compression) is intentionally not supported. Compression before encryption leaks information about plaintext through ciphertext size variations (CRIME/BREACH-style attacks). JWEs with zip set are rejected during parsing.

JSON Serialization Limitations

Types

Phantom type for AES-GCM Key Wrap algorithms (A128GCMKW, A192GCMKW, A256GCMKW).

pub type AesGcmKw

Phantom type for AES Key Wrap algorithms (A128KW, A192KW, A256KW).

pub type AesKw

Phantom type for JWE created via builder (new_*).

pub type Built

Phantom type for ChaCha20-Poly1305 Key Wrap algorithms (C20PKW, XC20PKW).

pub type ChaCha20Kw

A JWE decryptor that pins the expected algorithm and encryption method.

Use decryptors to prevent algorithm confusion attacks by specifying the expected algorithms upfront, rather than trusting the token’s header.

pub opaque type Decryptor

Phantom type for direct key encryption (dir).

pub type Direct

Phantom type for ECDH-ES algorithms (ECDH-ES, ECDH-ES+A*KW).

pub type EcdhEs

Phantom type for encrypted JWE (ciphertext present, can serialize/decrypt).

pub type Encrypted

A JSON Web Encryption with phantom types for state, algorithm family, and origin.

The origin phantom type distinguishes between JWE created via builders (Built) and JWE obtained by parsing tokens (Parsed). This enables compile-time enforcement that decode_*_unprotected_header only works on parsed instances.

pub opaque type Jwe(state, family, origin)

Phantom type for JWE obtained by parsing a token.

pub type Parsed

Phantom type for PBES2 algorithms (PBES2-HS*+A*KW).

pub type Pbes2

Phantom type for RSA key encryption algorithms (RSA1_5, RSA-OAEP, RSA-OAEP-256).

pub type Rsa

Phantom type for unencrypted JWE (plaintext set, ready to encrypt).

pub type Unencrypted

Values

pub fn aad(
  jwe: Jwe(Encrypted, family, origin),
) -> Result(BitArray, Nil)

Get the Additional Authenticated Data (AAD) from an encrypted JWE.

Returns Ok(aad) if AAD was set, Error(Nil) if not. AAD is only present in JSON serialization; compact format never has AAD.

Parameters

  • jwe - The encrypted JWE to read AAD from.

Returns

Ok(BitArray) with the AAD, or Error(Nil) if no AAD is present.

pub fn alg(jwe: Jwe(state, family, origin)) -> jwa.JweAlg

Get the key encryption algorithm (alg) from a JWE.

Parameters

  • jwe - The JWE to read the algorithm from.

Returns

The JweAlg key encryption algorithm.

pub fn cty(
  jwe: Jwe(state, family, origin),
) -> Result(String, Nil)

Get the content type (cty) from a JWE header.

Parameters

  • jwe - The JWE to read the content type from.

Returns

Ok(String) with the content type, or Error(Nil) if not set.

pub fn decode_shared_unprotected_header(
  jwe: Jwe(Encrypted, family, Parsed),
  decoder: decode.Decoder(a),
) -> Result(a, gose.GoseError)

Decode the shared unprotected header using a custom decoder.

Security Warning: Shared unprotected headers are NOT integrity protected. Values can be modified by an attacker without detection. Never trust security-critical parameters from unprotected headers.

This function only works on parsed JWE instances. When building a JWE, you already know what unprotected headers you set - use has_shared_unprotected_header to check their presence.

Returns an error if no shared unprotected headers are present.

Parameters

  • jwe - The parsed encrypted JWE to decode headers from.
  • decoder - A decoder for the expected header structure.

Returns

Ok(a) with the decoded shared unprotected header value, or Error(GoseError) if no shared unprotected headers are present or decoding fails.

Example

let decoder = {
  use id <- decode.field("x-request-id", decode.string)
  decode.success(id)
}
let assert Ok(request_id) =
  jwe.decode_shared_unprotected_header(parsed_jwe, decoder)
pub fn decode_unprotected_header(
  jwe: Jwe(Encrypted, family, Parsed),
  decoder: decode.Decoder(a),
) -> Result(a, gose.GoseError)

Decode the per-recipient unprotected header using a custom decoder.

Security Warning: Per-recipient unprotected headers are NOT integrity protected. Values can be modified by an attacker without detection. Never trust security-critical parameters from unprotected headers.

This function only works on parsed JWE instances. When building a JWE, you already know what unprotected headers you set - use has_unprotected_header to check their presence.

Returns an error if no per-recipient unprotected headers are present.

Parameters

  • jwe - The parsed encrypted JWE to decode headers from.
  • decoder - A decoder for the expected header structure.

Returns

Ok(a) with the decoded per-recipient unprotected header value, or Error(GoseError) if no per-recipient unprotected headers are present or decoding fails.

Example

let decoder = {
  use id <- decode.field("x-recipient-id", decode.string)
  decode.success(id)
}
let assert Ok(recipient_id) =
  jwe.decode_unprotected_header(parsed_jwe, decoder)
pub fn decrypt(
  decryptor: Decryptor,
  jwe: Jwe(Encrypted, family, origin),
) -> Result(BitArray, gose.GoseError)

Decrypt a JWE using a decryptor with algorithm pinning.

This is the recommended way to decrypt JWEs as it prevents algorithm confusion attacks by validating that the token’s algorithms match the expected algorithms configured in the decryptor.

Parameters

  • decryptor - A decryptor that pins the expected algorithms and provides keys or a password.
  • jwe - The encrypted JWE to decrypt.

Returns

Ok(BitArray) with the decrypted plaintext, or Error(GoseError) if algorithm validation fails, the key is wrong, or decryption fails.

Example

// Create a decryptor that only accepts A256GCM with direct encryption
let assert Ok(decryptor) = jwe.key_decryptor(jwa.JweDirect, jwa.AesGcm(jwa.Aes256), [key])

// This will fail if the token uses a different algorithm
let assert Ok(plaintext) = jwe.decrypt(decryptor, jwe)
pub fn enc(jwe: Jwe(state, family, origin)) -> jwa.Enc

Get the content encryption algorithm (enc) from a JWE.

Parameters

  • jwe - The JWE to read the encryption algorithm from.

Returns

The Enc content encryption algorithm.

pub fn encrypt(
  jwe: Jwe(Unencrypted, family, Built),
  key key: jwk.Jwk,
  plaintext plaintext: BitArray,
) -> Result(Jwe(Encrypted, family, Built), gose.GoseError)

Encrypt a JWE using the appropriate key-based algorithm.

Dispatches to the correct key encryption method based on the algorithm selected when the JWE was created. Supports direct, AES Key Wrap, AES-GCM Key Wrap, RSA, and ECDH-ES algorithms.

For PBES2 password-based algorithms, use encrypt_with_password instead.

JWK metadata (use, key_ops) is enforced when present:

  • Keys with use=sig are rejected
  • Keys with key_ops that don’t include encrypt or wrapKey are rejected

Parameters

  • jwe - The unencrypted JWE to encrypt.
  • key - The encryption key (type must match the algorithm).
  • plaintext - The data to encrypt.

Returns

Ok(Jwe(Encrypted, family, Built)) with the encrypted JWE, or Error(GoseError) if the key is invalid, the algorithm is PBES2, or encryption fails.

Example

let key = jwk.generate_enc_key(jwa.AesGcm(jwa.Aes256))
let assert Ok(encrypted) = jwe.new_direct(jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn encrypt_with_password(
  jwe: Jwe(Unencrypted, Pbes2, Built),
  password password: String,
  plaintext plaintext: BitArray,
) -> Result(Jwe(Encrypted, Pbes2, Built), gose.GoseError)

Encrypt a JWE using a password (PBES2).

Parameters

  • jwe - The unencrypted JWE to encrypt.
  • password - The password used for key derivation via PBKDF2.
  • plaintext - The data to encrypt.

Returns

Ok(Jwe(Encrypted, Pbes2, Built)) with the encrypted JWE, or Error(GoseError) if key derivation or encryption fails.

Example

let assert Ok(encrypted) = jwe.new_pbes2(jwa.Pbes2Sha256Aes128Kw, jwa.AesGcm(jwa.Aes128))
  |> jwe.encrypt_with_password("super-secret", <<"hello":utf8>>)
pub fn has_shared_unprotected_header(
  jwe: Jwe(Encrypted, family, origin),
) -> Bool

Check if shared unprotected headers are present.

Returns True if the JWE was parsed from JSON with shared unprotected headers, or if shared unprotected headers were added via with_shared_unprotected.

Parameters

  • jwe - The encrypted JWE to check.

Returns

True if shared unprotected headers are present, False otherwise.

pub fn has_unprotected_header(
  jwe: Jwe(Encrypted, family, origin),
) -> Bool

Check if per-recipient unprotected headers are present.

Returns True if the JWE was parsed from JSON with per-recipient unprotected headers, or if per-recipient unprotected headers were added via with_unprotected.

Parameters

  • jwe - The encrypted JWE to check.

Returns

True if per-recipient unprotected headers are present, False otherwise.

pub fn key_decryptor(
  alg: jwa.JweAlg,
  enc: jwa.Enc,
  keys keys: List(jwk.Jwk),
) -> Result(Decryptor, gose.GoseError)

Create a key-based decryptor for symmetric (dir, AES-KW, AES-GCM-KW) or asymmetric (RSA-OAEP, ECDH-ES) algorithms with multiple keys.

The decryptor pins the expected algorithm and encryption method. Tokens with different algorithms will be rejected.

When decrypting, keys are tried in order. If the JWE has a kid header, a key with matching kid is prioritized.

Parameters

  • alg - The expected key encryption algorithm.
  • enc - The expected content encryption algorithm.
  • keys - Candidate decryption keys, tried in order.

Returns

Ok(Decryptor) that can be passed to decrypt, or Error(GoseError) if the key list is empty or any key fails validation (all provided keys must pass algorithm-compatibility validation).

Example

let assert Ok(decryptor) = jwe.key_decryptor(jwa.JweDirect, jwa.AesGcm(jwa.Aes256), [key])
let assert Ok(plaintext) = jwe.decrypt(decryptor, encrypted_jwe)
pub fn kid(
  jwe: Jwe(state, family, origin),
) -> Result(String, Nil)

Get the key ID (kid) from a JWE header.

Parameters

  • jwe - The JWE to read the key ID from.

Returns

Ok(String) with the key ID, or Error(Nil) if not set.

pub fn new_aes_gcm_kw(
  size: jwa.AesKeySize,
  enc: jwa.Enc,
) -> Jwe(Unencrypted, AesGcmKw, Built)

Create a new unencrypted JWE for AES-GCM Key Wrap encryption. A random CEK is generated and wrapped using AES-GCM with the provided symmetric key.

Parameters

  • size - The AES key size variant to use.
  • enc - The content encryption algorithm to use.

Returns

An unencrypted Jwe with the AES-GCM Key Wrap family ready for encryption.

Example

let assert Ok(encrypted) = jwe.new_aes_gcm_kw(jwa.Aes256, jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn new_aes_kw(
  size: jwa.AesKeySize,
  enc: jwa.Enc,
) -> Jwe(Unencrypted, AesKw, Built)

Create a new unencrypted JWE for AES Key Wrap encryption. A random CEK is generated and wrapped with the provided symmetric key.

Parameters

  • size - The AES key size variant to use.
  • enc - The content encryption algorithm to use.

Returns

An unencrypted Jwe with the AES Key Wrap family ready for encryption.

Example

let assert Ok(encrypted) = jwe.new_aes_kw(jwa.Aes256, jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn new_chacha20_kw(
  variant: jwa.ChaCha20Kw,
  enc: jwa.Enc,
) -> Jwe(Unencrypted, ChaCha20Kw, Built)

Create a new unencrypted JWE for ChaCha20-Poly1305 Key Wrap encryption. A random CEK is generated and wrapped using ChaCha20-Poly1305 or XChaCha20-Poly1305 with the provided 32-byte symmetric key.

This is a non-standard extension (not defined in RFC 7518).

Parameters

  • variant - The ChaCha20 Key Wrap variant (C20PKw or XC20PKw).
  • enc - The content encryption algorithm to use.

Returns

An unencrypted Jwe with the ChaCha20 Key Wrap family ready for encryption.

Example

let assert Ok(encrypted) = jwe.new_chacha20_kw(jwa.XC20PKw, jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn new_direct(
  enc: jwa.Enc,
) -> Jwe(Unencrypted, Direct, Built)

Create a new unencrypted JWE for direct key encryption. The symmetric key is used directly as the Content Encryption Key (CEK).

Parameters

  • enc - The content encryption algorithm to use.

Returns

An unencrypted Jwe with the Direct family ready for encryption.

Example

let assert Ok(encrypted) = jwe.new_direct(jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn new_ecdh_es(
  alg: jwa.EcdhEsAlg,
  enc: jwa.Enc,
) -> Jwe(Unencrypted, EcdhEs, Built)

Create a new unencrypted JWE for ECDH-ES key agreement. An ephemeral key pair is generated during encryption for the key agreement.

Parameters

  • alg - The ECDH-ES algorithm variant to use.
  • enc - The content encryption algorithm to use.

Returns

An unencrypted Jwe with the ECDH-ES family ready for encryption.

Example

let assert Ok(encrypted) = jwe.new_ecdh_es(jwa.EcdhEsDirect, jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn new_pbes2(
  alg: jwa.Pbes2Alg,
  enc: jwa.Enc,
) -> Jwe(Unencrypted, Pbes2, Built)

Create a new unencrypted JWE for PBES2 password-based encryption. The CEK is derived from the password using PBKDF2.

Parameters

  • alg - The PBES2 algorithm variant to use.
  • enc - The content encryption algorithm to use.

Returns

An unencrypted Jwe with the PBES2 family ready for encryption. Use with_p2c to override the default iteration count. The salt is generated automatically.

Example

let assert Ok(encrypted) = jwe.new_pbes2(jwa.Pbes2Sha256Aes128Kw, jwa.AesGcm(jwa.Aes128))
  |> jwe.encrypt_with_password("secret", <<"hello":utf8>>)
pub fn new_rsa(
  alg: jwa.RsaJweAlg,
  enc: jwa.Enc,
) -> Jwe(Unencrypted, Rsa, Built)

Create a new unencrypted JWE for RSA key encryption. A random CEK is generated and encrypted with the RSA public key.

Parameters

  • alg - The RSA key encryption algorithm variant to use.
  • enc - The content encryption algorithm to use.

Returns

An unencrypted Jwe with the RSA family ready for encryption.

Example

let assert Ok(encrypted) = jwe.new_rsa(jwa.RsaOaepSha256, jwa.AesGcm(jwa.Aes256))
  |> jwe.encrypt(rsa_key, <<"hello":utf8>>)
pub fn parse_compact(
  token: String,
) -> Result(Jwe(Encrypted, Nil, Parsed), gose.GoseError)

Parse a JWE from compact format.

Returns an encrypted JWE that can be decrypted. Uses Nil family since algorithm family isn’t known at compile time.

Parameters

  • token - The compact-serialized JWE string to parse.

Returns

Ok(Jwe(Encrypted, Nil, Parsed)) with the parsed encrypted JWE, or Error(GoseError) if the token is malformed or contains invalid data.

Example

let assert Ok(parsed) = jwe.parse_compact(token)
let assert Ok(decryptor) = jwe.key_decryptor(jwa.JweDirect, jwa.AesGcm(jwa.Aes256), [key])
let assert Ok(plaintext) = jwe.decrypt(decryptor, parsed)
pub fn parse_json(
  json_str: String,
) -> Result(Jwe(Encrypted, Nil, Parsed), gose.GoseError)

Parse a JWE from JSON format (supports both General and Flattened).

Parameters

  • json_str - The JSON string to parse.

Returns

Ok(Jwe(Encrypted, Nil, Parsed)) with the parsed encrypted JWE, or Error(GoseError) if the JSON is malformed or contains invalid data.

pub fn password_decryptor(
  alg: jwa.Pbes2Alg,
  enc: jwa.Enc,
  password password: String,
) -> Decryptor

Create a password-based decryptor for PBES2 algorithms.

The decryptor pins the expected algorithm and encryption method. Tokens with different algorithms will be rejected.

Parameters

  • alg - The expected PBES2 key encryption algorithm.
  • enc - The expected content encryption algorithm.
  • password - The password used for key derivation.

Returns

A Decryptor that can be passed to decrypt to decrypt a PBES2-encrypted JWE.

Example

let decryptor = jwe.password_decryptor(
  jwa.Pbes2Sha256Aes128Kw,
  jwa.AesGcm(jwa.Aes128),
  "super-secret",
)
let assert Ok(plaintext) = jwe.decrypt(decryptor, encrypted_jwe)
pub fn serialize_compact(
  jwe: Jwe(Encrypted, family, Built),
) -> Result(String, gose.GoseError)

Serialize an encrypted JWE to compact format.

Format: {protected}.{encrypted_key}.{iv}.{ciphertext}.{tag}

Returns an error if AAD is set, since compact format does not support AAD. Use serialize_json_flattened or serialize_json_general for JWEs with AAD.

Parameters

  • jwe - The encrypted JWE to serialize.

Returns

Ok(String) with the JWE in compact serialization format, or Error(GoseError) if AAD or unprotected headers are present.

Example

let assert Ok(token) = jwe.serialize_compact(encrypted)
// -> "eyJhbGci...ciphertext...tag"
pub fn serialize_json_flattened(
  jwe: Jwe(Encrypted, family, Built),
) -> json.Json

Serialize an encrypted JWE to JSON Flattened format.

Format: {"protected":"...","encrypted_key":"...","iv":"...","ciphertext":"...","tag":"..."}

Note: This implementation supports a single recipient only. For Direct or ECDH-ES algorithms, the encrypted_key field is omitted. When AAD is present, includes the aad field. When unprotected headers are present, includes the unprotected and/or header fields.

Parameters

  • jwe - The encrypted JWE to serialize.

Returns

The JWE as a json.Json value in Flattened JSON Serialization format.

pub fn serialize_json_general(
  jwe: Jwe(Encrypted, family, Built),
) -> json.Json

Serialize an encrypted JWE to JSON General format.

Format: {"protected":"...","recipients":[{"encrypted_key":"..."}],"iv":"...","ciphertext":"...","tag":"..."}

Note: This implementation supports a single recipient only. Multiple recipients are not supported per RFC 7516 General Serialization. For Direct or ECDH-ES algorithms, the encrypted_key field is omitted. When AAD is present, includes the aad field. When unprotected headers are present, includes the unprotected field and/or the header field in the recipient object.

Parameters

  • jwe - The encrypted JWE to serialize.

Returns

The JWE as a json.Json value in General JSON Serialization format.

pub fn typ(
  jwe: Jwe(state, family, origin),
) -> Result(String, Nil)

Get the type (typ) from a JWE header.

Parameters

  • jwe - The JWE to read the type from.

Returns

Ok(String) with the type, or Error(Nil) if not set.

pub fn with_aad(
  jwe: Jwe(Unencrypted, family, Built),
  aad: BitArray,
) -> Jwe(Unencrypted, family, Built)

Set the Additional Authenticated Data (AAD) for JSON serialization.

AAD is only supported in JSON serialization (flattened and general formats). Attempting to serialize to compact format with AAD set will return an error.

Per RFC 7516, AAD is included in the AEAD authentication but is not encrypted.

Parameters

  • jwe - The unencrypted JWE to add AAD to.
  • aad - The additional authenticated data.

Returns

The Jwe with AAD set.

pub fn with_apu(
  jwe: Jwe(Unencrypted, EcdhEs, Built),
  apu: BitArray,
) -> Jwe(Unencrypted, EcdhEs, Built)

Set the Agreement PartyUInfo (apu) for ECDH-ES algorithms.

Parameters

  • jwe - The unencrypted ECDH-ES JWE.
  • apu - The PartyUInfo value (typically an identifier for the sender).

Returns

The Jwe with the apu header set.

Example

let jwe = jwe.new_ecdh_es(jwa.EcdhEsDirect, jwa.AesGcm(jwa.Aes256))
  |> jwe.with_apu(<<"Alice":utf8>>)
  |> jwe.with_apv(<<"Bob":utf8>>)
let assert Ok(encrypted) = jwe
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn with_apv(
  jwe: Jwe(Unencrypted, EcdhEs, Built),
  apv: BitArray,
) -> Jwe(Unencrypted, EcdhEs, Built)

Set the Agreement PartyVInfo (apv) for ECDH-ES algorithms.

Parameters

  • jwe - The unencrypted ECDH-ES JWE.
  • apv - The PartyVInfo value (typically an identifier for the recipient).

Returns

The Jwe with the apv header set.

Example

let jwe = jwe.new_ecdh_es(jwa.EcdhEsDirect, jwa.AesGcm(jwa.Aes256))
  |> jwe.with_apu(<<"Alice":utf8>>)
  |> jwe.with_apv(<<"Bob":utf8>>)
let assert Ok(encrypted) = jwe
  |> jwe.encrypt(key, <<"hello":utf8>>)
pub fn with_cty(
  jwe: Jwe(Unencrypted, family, Built),
  cty: String,
) -> Jwe(Unencrypted, family, Built)

Set the content type (cty) header parameter.

Parameters

  • jwe - The unencrypted JWE.
  • cty - The content type string (e.g. "JWT").

Returns

The Jwe with the cty header set.

pub fn with_kid(
  jwe: Jwe(Unencrypted, family, Built),
  kid: String,
) -> Jwe(Unencrypted, family, Built)

Set the key ID (kid) header parameter.

Parameters

  • jwe - The unencrypted JWE.
  • kid - The key identifier string.

Returns

The Jwe with the kid header set.

pub fn with_p2c(
  jwe: Jwe(Unencrypted, Pbes2, Built),
  iterations: Int,
) -> Result(Jwe(Unencrypted, Pbes2, Built), gose.GoseError)

Set the PBES2 iteration count (p2c) for password-based encryption.

This allows customizing the PBKDF2 iteration count. Production should use a value tuned for the specific use case.

Returns an error if iterations is less than 1,000 or greater than 10,000,000.

Parameters

  • jwe - The unencrypted PBES2 JWE.
  • iterations - The PBKDF2 iteration count (must be between 1,000 and 10,000,000).

Returns

Ok(Jwe) with the updated iteration count, or Error(GoseError) if the iteration count is out of the allowed range.

Example

let assert Ok(jwe) =
  jwe.new_pbes2(jwa.Pbes2Sha256Aes128Kw, jwa.AesGcm(jwa.Aes128))
  |> jwe.with_p2c(100_000)
pub fn with_shared_unprotected(
  jwe: Jwe(Unencrypted, family, Built),
  name: String,
  value: json.Json,
) -> Result(Jwe(Unencrypted, family, Built), gose.GoseError)

Add a shared unprotected header parameter.

Security Warning: Shared unprotected headers are NOT integrity protected. They can be modified by an attacker without detection.

Returns an error if the name is a protected-only header (alg, enc, crit, zip) which must be integrity protected.

Shared unprotected headers apply to all recipients in JSON serialization. Compact serialization will return an error if unprotected headers are present.

If the same header name is set multiple times, the last value wins.

Parameters

  • jwe - The unencrypted JWE to add the header to.
  • name - The header parameter name.
  • value - The header parameter value as JSON.

Returns

Ok(Jwe) with the added shared unprotected header, or Error(GoseError) if the name is a protected-only header.

Example

let assert Ok(jwe) =
  jwe.new_direct(jwa.AesGcm(jwa.Aes256))
  |> jwe.with_shared_unprotected("x-request-id", json.string("abc-123"))
pub fn with_typ(
  jwe: Jwe(Unencrypted, family, Built),
  typ: String,
) -> Jwe(Unencrypted, family, Built)

Set the type (typ) header parameter (e.g., “JWT”).

Parameters

  • jwe - The unencrypted JWE.
  • typ - The type string (e.g. "JWT").

Returns

The Jwe with the typ header set.

pub fn with_unprotected(
  jwe: Jwe(Unencrypted, family, Built),
  name: String,
  value: json.Json,
) -> Result(Jwe(Unencrypted, family, Built), gose.GoseError)

Add a per-recipient unprotected header parameter.

Security Warning: Per-recipient unprotected headers are NOT integrity protected. They can be modified by an attacker without detection.

Returns an error if the name is a protected-only header (alg, enc, crit, zip) which must be integrity protected.

Per-recipient headers appear in JSON serialization only and apply to the single recipient. Compact serialization will return an error if unprotected headers are present.

If the same header name is set multiple times, the last value wins.

Parameters

  • jwe - The unencrypted JWE to add the header to.
  • name - The header parameter name.
  • value - The header parameter value as JSON.

Returns

Ok(Jwe) with the added per-recipient unprotected header, or Error(GoseError) if the name is a protected-only header.

Search Document