SpruceKit
SpruceID
  • 🌲SpruceKit Introduction
    • Decentralized Identity Overview
    • Glossary
  • ⚡Quickstart
  • SpruceKit Mobile
    • SpruceKit Showcase App
      • Installation
      • Getting Started
      • Issue a Showcase Credential
      • Present a Showcase Credential
    • SpruceKit Mobile SDK
      • Introduction
      • Core Components
        • StorageManager
        • KeyManager
        • CredentialPack
        • Card
        • IsoMdlPresentation
        • mDocReader/IsomDLReader
        • Document Scanner
      • SpruceKit iOS SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
      • SpruceKit Android SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present an mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
  • Verifiable Digital Credentials
    • ⚙️DIDKit
      • Installation
      • Core Concepts
      • DID Methods
      • Runtime Configuration
      • Specifications and Dependencies
      • Quickstart
      • DIDKit Packages
        • Command Line Interface
        • HTTP Server
        • Rust Crate
        • C Interface
        • Java and Android
        • Python
        • Javascript
      • DIDKit Examples
        • Core Functions (CLI)
        • Core Functions (HTTP)
        • did-web in minutes
        • Batch Generation & Verification
    • 🪪ISO mDL
      • Quickstart
      • Core Concepts
      • User Guide
  • Schema Definition Language
    • 🔗TreeLDR
      • TreeLDR Quickstart
        • First Schema
        • Compilation into JSON Schema
        • Compilation into JSON-LD Context
        • Writing a Layout
        • Simple Rust Integration
      • Types
        • Literal Types
      • Layouts
        • Primitive Layouts
        • Literal Layouts
        • Enumeration
        • Array Layout
        • References
      • Compiling
        • Schema Definition Formats
          • JSON Schema
          • JSON-LD Context
          • Resource Description Framework (RDF)
        • Programming Languages
          • Compiling to Rust
      • RDF Vocabulary
      • 💡TreeLDR Basics
        • Types and Layouts
        • Properties
        • Syntax
  • Witness for Credential Claims
    • 🔭Rebase
      • Core Library
      • Rust Client/Witness SDK
      • WASM Client SDK
      • Simple "Basic Post" Schema
      • DNS Witness Flow Schema
  • References
    • Contributing
    • Code of Conduct
Powered by GitBook
On this page
  • Initialize a Session
  • Session Data
  • Session Request
  • Session Request
  • Session Manager
  • Session Response

Was this helpful?

  1. Verifiable Digital Credentials
  2. ISO mDL

User Guide

This user guide demonstrates building an application that can verify and/or share mDLs with the SpruceID Rust ISOmDL library.

PreviousCore ConceptsNextTreeLDR

Last updated 6 months ago

Was this helpful?

See more examples and simulated device and reader test cases at the open source GitHub repository:

Available device retrieval methods include WiFi, BLE, and NFC. More than one device retrieval method may be accessible for the session.

Initialize a Session

Devices store verifiable documents and create sessions that allow Readers to request this verifiable data. To start a new session, the device uses the device module to call the SessionManagerInit::initialize method. This method provides the Reader with a list of available documents that can be presented, as well as any optional DeviceRetrievalMethods that can be used to transfer the data.

Device retrieval methods include WiFi, BLE (Bluetooth Low Energy), and NFC. During the session, more than one method can be made available.

Additionally, the device can optionally specify a remote server retrieval method for data transfer, using the ServerRetrievalMethods type.

Example

/// Creates a QR code containing `DeviceEngagement` data, 
/// which includes its public key.
fn initialize_session(docs: Documents, id: Uuid) -> Result<SessionData> {
    let device_retrieval_methods = DeviceRetrievalMethods::new(
        DeviceRetrievalMethod::BLE(BleOptions {
        peripheral_server_mode: None,
        central_client_mode: Some(CentralClientMode { id }),
    }));

    let session = device::SessionManagerInit::initialize(
        docs, 
        Some(device_retrieval_methods), None
        )
        .context("failed to initialize device")?;

    let (engaged_state, qr_code_uri) = session
        .qr_engagement()
        .context("could not generate qr engagement")?;
    Ok(SessionData {
        state: Arc::new(SessionManagerEngaged(engaged_state)),
        qr_code_uri,
    })
}

Session Data

Once the session data is established, the device can share the QR code URI created by the qr_engagement method with the reader. In an mDL wallet application, this typically looks like a QR code displayed on the mobile driver's license card. The Reader will use the QR code URI, along with a request element to establish a reader session.

Example

/// Establishes the reader session from the given QR code and create request for needed elements.
const AGE_OVER_21_ELEMENT: &str = "age_over_21";

fn establish_reader_session(qr_code_uri: String) -> Result<(reader::SessionManager, Vec<u8>)> {
    let requested_elements = Namespaces::new(
        NAMESPACE.into(),
        DataElements::new(AGE_OVER_21_ELEMENT.to_string(), false),
    );
    let (reader_sm, session_request, _ble_ident) =
        reader::SessionManager::establish_session(qr, requested_elements)
            .context("failed to establish reader session")?;
    Ok((reader_sm, session_request))
}

Session Request

Session Request

Once the Reader has established a session with the necessary request elements using the establish_session method, a CBOR-serialized byte payload called session_request is returned, which is then sent to the device for processing.

When the device receives the session request, it deserializes the raw CBOR bytes and processes the session establishment by calling the SessionManagerEngage::process_session_establishment method. After processing the session request, a SessionManager instance is returned. Session Manager

Session Manager

The SessionManager instance offers a prepare_response method, which processes the requested session items based on a set of permitted items. This method updates the internal state of the device session to "Signing."

When the SessionManager is in the Signing state, the get_next_signature_payload method is used to return the payloads that need to be signed. These payloads are signed using the SessionManager's private key.

Once a payload is signed, the submit_next_signature method is called to update the internal state of the SessionManager with the signed messages. After the signature is submitted, the device prepares an encrypted response using the shared key that was established during session setup. The internal state of the SessionManager is then set to "ReadyToRespond," along with the CBOR-serialized encrypted response.

Example

// Prepare response with required elements.
fn create_response(session_manager: Arc<SessionManager>) -> Result<Vec<u8>> {
    let permitted_items = [(
        DOC_TYPE.to_string(),
        [(NAMESPACE.to_string(), vec![AGE_OVER_21_ELEMENT.to_string()])]
            .into_iter()
            .collect(),
    )]
    .into_iter()
    .collect();
    session_manager
        .inner
        .lock()
        .unwrap()
        .prepare_response(&session_manager.items_requests, permitted_items);
    sign_pending_and_retrieve_response(session_manager.clone(), Some(1))?
        .ok_or_else(|| anyhow::anyhow!("cannot prepare response"))
}

Session Response

Once the response has been prepared, the SessionManager provides a retrieve_response method that can be used to return the documents that have been signed by the device. The response is sent to the reader and processed by the reader's session manager, using the handle_response method.

Example

/// Reader Processing mDL data.
fn reader_handle_device_response(
    reader_sm: &mut reader::SessionManager,
    response: Vec<u8>,
) -> Result<()> {
    let res = reader_sm.handle_response(&response)?;
    println!("{:?}", res);
    Ok(())
}

Based on the result of the handle_response method, the verifier of the mDL can decide to provide or deny access to the mDL holder or to continue with any other business logic.

Based on the result of the handle_response method, the verifier of the mDL can decide to provide or deny access to the mDL holder or to continue with any other business logic.

The isomdl library currently only supports data elements belonging to the core namespace defined in the ISO/IEC 18013-5 specification along with the namespace defined by AAMVA for mDLs issued by US states. If your needs exceed what is currently offered, we invite you to file an issue on our

The isomdl library currently only supports data elements belonging to the core namespace defined in the ISO/IEC 18013-5 specification, along with the namespace defined by AAMVA for mDLs issued by US states. If your needs exceed what is currently offered, we invite you to file an issue on our .

🪪
https://github.com/spruceid/isomdl
github repository
github repository