#mdl #tbtl #openid4vc #detail #mdoc

bhmdoc

TBTL's library for handling mDL/mdoc specification

2 unstable releases

new 0.2.0 Apr 24, 2025
0.1.0 Apr 22, 2025

#441 in Authentication

Download history 64/week @ 2025-04-16

64 downloads per month

Custom license

370KB
6K SLoC

bhmdoc

This library provides functionality for working with the mDL/mdoc specification as defined in ISO/IEC 18013-5 and expanded on in ISO/IEC TS 18013-7:2024 to include integration with openid4vc.

Details

The primary way to use this library is to use the Issuer, Device and Verifier structs to issue, present and verify issued mdoc documents as defined in the openid4vc specifications.

For additional documentation & examples, take a look at the crate documentation.

Changelog

The changelog can be found here.

License

Licensed under GNU Affero General Public License, Version 3.


lib.rs:

This crate provides the functionality for handling mobile driving licenses (mDLs) and other mso_mdoc Credentials in compliance with the ISO/IEC 18013-5:2021 & ISO/IEC TS 18013-7:2024 standards, but modified to work with OpenID for Verifiable Presentations and Verifiable Credential Issuance specifications.

Details

The crate defines multiple modules, which can be roughly divided as follows.

A typical user of this crate is expected to care only about the high-level modules. The lower level data model is exposed for advanced users wishing to adapt the crate to their mso_mdoc use case.

Examples

The bhmdoc repository contains the full examples, so you should take a look there to see how things fit together.

Here we will just summarize the most common use cases of the crate.

Issuing a Mobile Driving License (mDL)

use std::str::FromStr;

use bhmdoc::models::{
    mdl::*,
    FullDate,
};

let mut rng = rand::thread_rng();
let issuer_signer = _; // Implementation of [`bh_jws_utils::Signer`]
let device_key = _; // Instance of [`bhmdoc::DeviceKey`].
let current_time = 100;

let mdl_mandatory = MDLMandatory {
    family_name: "Doe".to_owned(),
    given_name: "John".to_owned(),
    birth_date: "1980-01-02".parse().unwrap(),
    issue_date: FullDate::from_str("2024-01-01").unwrap().into(),
    expiry_date: FullDate::from_str("2029-01-01").unwrap().into(),
    issuing_authority: "MUP".to_owned(),
    issuing_country: "RH".to_owned(),
    document_number: "1234".to_owned(),
    portrait: vec![1u8, 2, 3].into(),
    driving_privileges: 7,
    un_distinguishing_sign: "sign".to_owned(),
};

let mdl = MDL::new(mdl_mandatory);

let issued = bhmdoc::Issuer
    .issue_mdl(mdl, device_key, &issuer_signer, &mut rng, current_time)
    .unwrap();

Verifying an Issued mso_mdoc Credential

let verifier = bhmdoc::Verifier::from_parts(
    "example verifier client id".to_owned(),
    "https://example.response.uri".to_owned(),
    "example nonce".to_owned(),
);

// `vp_token` as per <https://openid.net/specs/openid-4-verifiable-presentations-1_0.html>
let vp_token = "Base64url encoded Verifiable Presentation";
let device_response = bhmdoc::models::DeviceResponse::from_base64_cbor(vp_token).unwrap();
let current_time = 100;

// This should return `Some(bh_jws_utils::SignatureVerifier)`
// based on the received `bh_jws_utils::SigningAlgorithm`.
let get_signature_verifier = |_alg| None;

let claims = verifier
    .verify(
        device_response,
        current_time,
        "example mdoc generated nonce",
        get_signature_verifier,
    )
    .unwrap();

Dependencies

~9MB
~183K SLoC