Decoder

Struct Decoder 

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

Builder for decoding Claim 169 credentials from QR strings.

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

§Operation Order

When both decryption and verification are configured, the credential is always decrypted first, then verified (reverse of encoding), regardless of the order in which builder methods are called.

§Security

  • By default, decoding requires signature verification
  • Use allow_unverified() to explicitly opt out
  • Decompression is limited to prevent zip bomb attacks (default: 64KB)

§Example

use claim169_core::Decoder;

let result = Decoder::new("6BF5YZB2...")
    .verify_with_ed25519(&public_key)?
    .decode()?;

println!("ID: {:?}", result.claim169.id);
println!("Verified: {:?}", result.verification_status);

Implementations§

Source§

impl Decoder

Source

pub fn new(qr_text: impl Into<String>) -> Self

Create a new decoder with the given QR text.

§Arguments
  • qr_text - The Base45-encoded QR code content (accepts &str or String)
§Example
let decoder = Decoder::new("6BF5YZB2...");
let decoder = Decoder::new(qr_string);
Source

pub fn verify_with<V: SignatureVerifier + 'static>(self, verifier: V) -> Self

Verify with a custom verifier implementation.

Use this method for HSM integration or custom cryptographic backends.

§Arguments
§Example
let decoder = Decoder::new(qr_text)
    .verify_with(hsm_verifier);
Source

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

Verify with an Ed25519 public key.

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

§Arguments
  • public_key - 32-byte Ed25519 public key
§Errors

Returns an error if the public key is invalid or represents a weak key.

§Example
let decoder = Decoder::new(qr_text)
    .verify_with_ed25519(&public_key)?;
Source

pub fn verify_with_ed25519_pem(self, pem: &str) -> Result<Self>

Verify with an Ed25519 public key in PEM format.

Supports SPKI format with “BEGIN PUBLIC KEY” headers.

§Arguments
  • pem - PEM-encoded Ed25519 public key
§Errors

Returns an error if the PEM is invalid or the key is weak.

Source

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

Verify with an ECDSA P-256 public key.

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

§Arguments
  • public_key - SEC1-encoded P-256 public key (33 or 65 bytes)
§Errors

Returns an error if the public key format is invalid or represents a weak key.

Source

pub fn verify_with_ecdsa_p256_pem(self, pem: &str) -> Result<Self>

Verify with an ECDSA P-256 public key in PEM format.

Supports SPKI format with “BEGIN PUBLIC KEY” headers.

§Arguments
  • pem - PEM-encoded P-256 public key
§Errors

Returns an error if the PEM is invalid or the key is weak.

Source

pub fn decrypt_with<D: Decryptor + 'static>(self, decryptor: D) -> Self

Decrypt with a custom decryptor implementation.

Use this method for HSM integration or custom cryptographic backends.

§Arguments
  • decryptor - A type implementing the Decryptor trait
Source

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

Decrypt with AES-256-GCM.

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

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

Source

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

Decrypt with AES-128-GCM.

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

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

Source

pub fn allow_unverified(self) -> Self

Allow decoding without signature verification.

Security Warning: Unverified credentials cannot be trusted for authenticity. Only use this for testing or when verification is handled externally.

§Example
let result = Decoder::new(qr_text)
    .allow_unverified()
    .decode()?;
Source

pub fn skip_biometrics(self) -> Self

Skip biometric fields during decoding.

This speeds up decoding by not parsing fingerprint, iris, face, palm, and voice biometric data.

Source

pub fn without_timestamp_validation(self) -> Self

Disable timestamp validation.

By default, the decoder validates that:

  • The credential has not expired (exp claim)
  • The credential is valid for use (nbf claim)

Use this method to skip these checks (e.g., for offline scenarios).

Source

pub fn clock_skew_tolerance(self, seconds: i64) -> Self

Set the clock skew tolerance for timestamp validation.

This allows for some difference between the system clock and the issuer’s clock when validating exp and nbf claims.

§Arguments
  • seconds - Number of seconds to tolerate (default: 0)
Source

pub fn max_decompressed_bytes(self, bytes: usize) -> Self

Set the maximum decompressed size.

This protects against zip bomb attacks by limiting how much data can be decompressed from the QR payload.

§Arguments
  • bytes - Maximum decompressed size in bytes (default: 65536)
Source

pub fn decode(self) -> Result<DecodeResult>

Decode the QR text and return the result.

This method consumes the decoder and performs the full decoding pipeline:

Base45 → zlib → COSE_Encrypt0 → COSE_Sign1 → CWT → Claim169
§Errors

Returns an error if:

  • Neither a verifier nor allow_unverified() was configured
  • Base45 decoding fails
  • Decompression fails or exceeds the limit
  • COSE structure is invalid
  • Signature verification fails
  • Decryption fails
  • CWT parsing fails
  • Timestamp validation fails
§Example
let result = Decoder::new(qr_text)
    .verify_with_ed25519(&public_key)?
    .decode()?;

println!("Name: {:?}", result.claim169.full_name);

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