Encoder

Struct Encoder 

Source
pub struct Encoder { /* private fields */ }
Expand description

Builder for encoding Claim 169 credentials into QR-ready strings.

The encoder follows a builder pattern where configuration methods return Self and the final encode() method consumes the builder to produce the result.

§Operation Order

When both signing and encryption are configured, the credential is always signed first, then encrypted (sign-then-encrypt), regardless of the order in which builder methods are called.

§Security

  • Unsigned encoding requires explicit opt-in via allow_unsigned()
  • Nonces are generated randomly by default for encryption
  • Use explicit nonce methods only for testing or deterministic scenarios

§Example

use claim169_core::{Encoder, Claim169, CwtMeta};

let claim169 = Claim169::minimal("ID-001", "Jane Doe");
let cwt_meta = CwtMeta::new()
    .with_issuer("https://issuer.example.com")
    .with_expires_at(1800000000);

// Sign with Ed25519
let qr_data = Encoder::new(claim169, cwt_meta)
    .sign_with_ed25519(&private_key)?
    .encode()?;

Implementations§

Source§

impl Encoder

Source

pub fn new(claim169: Claim169, cwt_meta: CwtMeta) -> Self

Create a new encoder with the given claim and CWT metadata.

§Arguments
  • claim169 - The identity claim data to encode
  • cwt_meta - CWT metadata including issuer, expiration, etc.
§Example
let encoder = Encoder::new(claim169, cwt_meta);
Source

pub fn sign_with<S: Signer + 'static>( self, signer: S, algorithm: Algorithm, ) -> Self

Sign with a custom signer implementation.

Use this method for HSM integration or custom cryptographic backends.

§Arguments
  • signer - A type implementing the Signer trait
  • algorithm - The COSE algorithm to use for signing
§Example
let encoder = Encoder::new(claim169, cwt_meta)
    .sign_with(hsm_signer, iana::Algorithm::EdDSA);
Source

pub fn sign_with_ed25519(self, private_key: &[u8]) -> Result<Self>

Sign with an Ed25519 private key.

The key is validated immediately and an error is returned if invalid.

§Arguments
  • private_key - 32-byte Ed25519 private key
§Errors

Returns an error if the private key is not exactly 32 bytes.

§Example
let encoder = Encoder::new(claim169, cwt_meta)
    .sign_with_ed25519(&private_key)?;
Source

pub fn sign_with_ecdsa_p256(self, private_key: &[u8]) -> Result<Self>

Sign with an ECDSA P-256 private key.

The key is validated immediately and an error is returned if invalid.

§Arguments
  • private_key - 32-byte ECDSA P-256 private key (scalar)
§Errors

Returns an error if the private key format is invalid.

§Example
let encoder = Encoder::new(claim169, cwt_meta)
    .sign_with_ecdsa_p256(&private_key)?;
Source

pub fn encrypt_with<E: Encryptor + 'static>( self, encryptor: E, algorithm: Algorithm, ) -> Self

Encrypt with a custom encryptor implementation.

Use this method for HSM integration or custom cryptographic backends. A random 12-byte nonce is generated automatically.

§Arguments
  • encryptor - A type implementing the Encryptor trait
  • algorithm - The COSE algorithm to use for encryption
Source

pub fn encrypt_with_aes256(self, key: &[u8]) -> Result<Self>

Encrypt with AES-256-GCM.

A random 12-byte nonce is generated automatically during encoding.

§Arguments
  • key - 32-byte AES-256 encryption key
§Errors

Returns an error if the key is not exactly 32 bytes.

§Example
let encoder = Encoder::new(claim169, cwt_meta)
    .sign_with_ed25519(&sign_key)?
    .encrypt_with_aes256(&aes_key)?;
Source

pub fn encrypt_with_aes128(self, key: &[u8]) -> Result<Self>

Encrypt with AES-128-GCM.

A random 12-byte nonce is generated automatically during encoding.

§Arguments
  • key - 16-byte AES-128 encryption key
§Errors

Returns an error if the key is not exactly 16 bytes.

Source

pub fn encrypt_with_aes256_nonce( self, key: &[u8], nonce: &[u8; 12], ) -> Result<Self>

Encrypt with AES-256-GCM using an explicit nonce.

Warning: Only use this for testing or deterministic scenarios. Reusing nonces with the same key is a critical security vulnerability.

§Arguments
  • key - 32-byte AES-256 encryption key
  • nonce - 12-byte nonce/IV (must be unique per encryption)
Source

pub fn encrypt_with_aes128_nonce( self, key: &[u8], nonce: &[u8; 12], ) -> Result<Self>

Encrypt with AES-128-GCM using an explicit nonce.

Warning: Only use this for testing or deterministic scenarios. Reusing nonces with the same key is a critical security vulnerability.

§Arguments
  • key - 16-byte AES-128 encryption key
  • nonce - 12-byte nonce/IV (must be unique per encryption)
Source

pub fn allow_unsigned(self) -> Self

Allow encoding without a signature.

Security Warning: Unsigned credentials cannot be verified for authenticity. Only use this for testing or scenarios where signatures are not required.

§Example
let encoder = Encoder::new(claim169, cwt_meta)
    .allow_unsigned()
    .encode()?;
Source

pub fn skip_biometrics(self) -> Self

Skip biometric fields during encoding.

This reduces the QR code size by excluding fingerprint, iris, face, palm, and voice biometric data.

§Example
let encoder = Encoder::new(claim169, cwt_meta)
    .skip_biometrics()
    .sign_with_ed25519(&key)?
    .encode()?;
Source

pub fn encode(self) -> Result<String>

Encode the credential to a Base45 QR string.

This method consumes the encoder and produces the final QR-ready string.

§Pipeline
Claim169 → CBOR → CWT → COSE_Sign1 → [COSE_Encrypt0] → zlib → Base45
§Errors

Returns an error if:

  • Neither a signer nor allow_unsigned() was configured
  • Signing fails
  • Encryption fails
  • CBOR encoding fails
§Example
let qr_data = Encoder::new(claim169, cwt_meta)
    .sign_with_ed25519(&key)?
    .encode()?;

println!("QR content: {}", qr_data);

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V