SdJwt.Net.Mdoc 1.0.2

dotnet add package SdJwt.Net.Mdoc --version 1.0.2
                    
NuGet\Install-Package SdJwt.Net.Mdoc -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SdJwt.Net.Mdoc" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SdJwt.Net.Mdoc" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="SdJwt.Net.Mdoc" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SdJwt.Net.Mdoc --version 1.0.2
                    
#r "nuget: SdJwt.Net.Mdoc, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SdJwt.Net.Mdoc@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SdJwt.Net.Mdoc&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=SdJwt.Net.Mdoc&version=1.0.2
                    
Install as a Cake Tool

SdJwt.Net.Mdoc - ISO 18013-5 Mobile Document Support

NuGet Version License

ISO 18013-5 mDL/mdoc implementation for the SD-JWT .NET ecosystem. Provides credential issuance, presentation, and verification for mobile document credentials with OpenID4VP/OpenID4VCI integration and HAIP compliance.

Overview

This package provides complete support for ISO 18013-5 mobile documents (mdoc), including:

  • Mobile Driving License (mDL): ISO 18013-5 compliant driver's license credentials
  • CBOR/COSE Encoding: Native support for CBOR serialization and COSE signing
  • Selective Disclosure: Privacy-preserving attribute sharing for mdoc credentials
  • OpenID4VP Integration: Present mdoc credentials via OpenID for Verifiable Presentations
  • OpenID4VCI Integration: Issue mdoc credentials via OpenID for Verifiable Credential Issuance
  • HAIP Compliance: High Assurance Interoperability Profile support
  • Proximity Presentation: QR code, NFC, and BLE-based credential sharing

Supported Document Types

Document Type Standard Status
mDL ISO 18013-5 Stable
PID EU ARF (mdoc) Planned
mID ISO 23220-3 Planned
Custom Generic mdoc Stable

Installation

dotnet add package SdJwt.Net.Mdoc

For complete OpenID4VC functionality:

dotnet add package SdJwt.Net.Oid4Vci    # Credential Issuance
dotnet add package SdJwt.Net.Oid4Vp     # Credential Presentation
dotnet add package SdJwt.Net.HAIP       # High Assurance Compliance

Quick Start

Issue a Mobile Driving License (mDL)

using SdJwt.Net.Mdoc;
using SdJwt.Net.Mdoc.Issuer;

// Create mdoc issuer with COSE signing
var signingKey = MdocKeyFactory.CreateECDsaKey(ECCurve.NamedCurves.nistP256);
var issuer = new MdocIssuer(signingKey);

// Define mDL claims per ISO 18013-5
var mdlClaims = new MdocClaims
{
    DocType = "org.iso.18013.5.1.mDL",
    Namespace = "org.iso.18013.5.1",
    Claims = new Dictionary<string, object>
    {
        ["family_name"] = "Doe",
        ["given_name"] = "Jane",
        ["birth_date"] = "1990-01-15",
        ["issue_date"] = "2023-01-01",
        ["expiry_date"] = "2028-01-01",
        ["issuing_country"] = "US",
        ["issuing_authority"] = "State of California DMV",
        ["document_number"] = "DL12345678",
        ["portrait"] = Convert.FromBase64String("..."), // Photo
        ["driving_privileges"] = new[]
        {
            new { vehicle_category_code = "A", issue_date = "2023-01-01" },
            new { vehicle_category_code = "B", issue_date = "2023-01-01" }
        }
    }
};

// Issue CBOR-encoded mdoc
var mdoc = await issuer.IssueAsync(mdlClaims);
Console.WriteLine($"mDL issued: {mdoc.Length} bytes (CBOR)");

Verify and Parse an mdoc

using SdJwt.Net.Mdoc.Verifier;

// Create mdoc verifier
var keyResolver = new TrustListKeyResolver();
var verifier = new MdocVerifier(keyResolver);

// Verify mdoc signature and validity
var verificationResult = await verifier.VerifyAsync(receivedMdoc);

if (verificationResult.IsValid)
{
    var parsedMdoc = verificationResult.ParsedDocument;

    Console.WriteLine($"Document Type: {parsedMdoc.DocType}");
    Console.WriteLine($"Issuer: {parsedMdoc.IssuerAuth.Issuer}");
    Console.WriteLine($"Valid Until: {parsedMdoc.ValidityInfo.ValidUntil}");

    // Access disclosed claims
    var familyName = parsedMdoc.Claims["family_name"];
    var birthDate = parsedMdoc.Claims["birth_date"];

    Console.WriteLine($"Holder: {familyName}, DOB: {birthDate}");
}
else
{
    Console.WriteLine($"Invalid mdoc: {verificationResult.ErrorDescription}");
}

Selective Disclosure with mdoc

using SdJwt.Net.Mdoc.Holder;

// Create mdoc holder
var holder = new MdocHolder(storedMdoc);

// Create presentation with selective disclosure
var presentationRequest = new MdocPresentationRequest
{
    DocType = "org.iso.18013.5.1.mDL",
    Namespace = "org.iso.18013.5.1",
    RequestedElements = new[]
    {
        "family_name",
        "given_name",
        "birth_date",
        "portrait",
        "age_over_21"  // Derived attribute
    }
};

// Generate device response (CBOR-encoded)
var deviceResponse = await holder.CreatePresentationAsync(
    presentationRequest,
    sessionTranscript: GenerateSessionTranscript(),
    readerPublicKey: verifierPublicKey
);

Console.WriteLine($"Presentation created: {deviceResponse.Length} bytes");
// Only requested attributes are disclosed

OpenID4VP Integration

Present mdoc via OpenID4VP

using SdJwt.Net.Oid4Vp;
using SdJwt.Net.Mdoc.Oid4Vp;

// Parse OpenID4VP authorization request
var vpRequest = await Oid4VpRequestParser.ParseAsync(authorizationRequestUri);

// Create mdoc presentation response
var mdocAdapter = new MdocOid4VpAdapter();
var vpResponse = await mdocAdapter.CreateResponseAsync(
    vpRequest,
    holder: mdocHolder,
    selectiveClaims: new[] { "family_name", "birth_date", "age_over_18" }
);

// Submit to verifier
await vpRequest.SubmitResponseAsync(vpResponse);

OpenID4VCI Integration

Receive mdoc via OpenID4VCI

using SdJwt.Net.Oid4Vci;
using SdJwt.Net.Mdoc.Oid4Vci;

// Process credential offer
var offer = await Oid4VciOfferParser.ParseAsync(credentialOfferUri);

// Request mdoc mDL credential
var mdocAdapter = new MdocOid4VciAdapter();
var issuedMdoc = await mdocAdapter.RequestCredentialAsync(
    offer,
    credentialType: "org.iso.18013.5.1.mDL",
    holderKeyPair: holdingKey,
    pinCode: userPin
);

// Store in wallet
await wallet.StoreMdocAsync(issuedMdoc);

Proximity Presentation

QR Code Engagement

using SdJwt.Net.Mdoc.Proximity;

// Start proximity presentation (QR code)
var proximityService = new ProximityPresentationService();
var engagement = await proximityService.StartQrEngagementAsync();

Console.WriteLine($"Display QR code: {engagement.QrCodeData}");

// Wait for reader connection
var request = await proximityService.ReceiveRequestAsync();

Console.WriteLine($"Reader requests: {string.Join(", ", request.RequestedElements)}");

// User consent
if (await GetUserConsent(request.RequestedElements))
{
    // Generate and send device response
    await proximityService.SendResponseAsync(
        request,
        disclosedElements: selectedElements,
        signingKey: deviceKey
    );

    Console.WriteLine("Presentation completed successfully");
}

NFC Presentation

// Enable NFC engagement (platform-specific)
await proximityService.EnableNfcEngagementAsync();

Console.WriteLine("NFC enabled - tap reader to begin");

// Handling is the same as QR code after engagement
var request = await proximityService.ReceiveRequestAsync();
// ... respond as above

HAIP Compliance

Enforce HAIP Level 2 for Government mDL

using SdJwt.Net.HAIP;

// Create HAIP-compliant mdoc issuer
var haipValidator = new HaipCryptoValidator(HaipLevel.Level2_VeryHigh, logger);

// Validate signing algorithm
if (!haipValidator.ValidateAlgorithm("ES384"))
{
    throw new InvalidOperationException("ES384 required for Level 2 HAIP");
}

// Use stronger key for Level 2
var haipKey = MdocKeyFactory.CreateECDsaKey(ECCurve.NamedCurves.nistP384);
var haipIssuer = new MdocIssuer(haipKey, algorithm: "ES384");

// Issue HAIP-compliant mDL
var haipMdl = await haipIssuer.IssueAsync(mdlClaims);

Features

CBOR/COSE Support

  • CBOR Serialization: Efficient binary encoding per CBOR specification
  • COSE Signing: Cryptographic signing with COSE_Sign1 structure
  • Tag Handling: Proper CBOR tag processing for dates, binary data, and custom types
  • Deterministic Encoding: Reproducible CBOR output for signature verification

Security Features

  • Device Binding: Cryptographic binding to holder's device key
  • Session Transcript: Prevents replay attacks in proximity scenarios
  • Reader Authentication: Validates reader certificate and permissions
  • Age Verification: Privacy-preserving age-over-X derived attributes
  • Revocation: Integration with Status List for credential lifecycle management

Privacy Features

  • Selective Disclosure: Share only requested attributes
  • Derived Attributes: Prove properties without revealing underlying data (e.g., age_over_21)
  • Unlinkability: Different presentations cannot be correlated
  • Minimal Disclosure: Request only what is needed per privacy-by-design

Advanced Usage

Device Engagement and Session Establishment

// Generate device engagement with mdoc holder information
var deviceEngagement = new DeviceEngagement
{
    Version = "1.0",
    Security = new Security
    {
        CipherSuites = new[] { 1 }, // ECDHE with AES-GCM
        DeviceKey = holderPublicKey
    },
    DeviceRetrievalMethods = new[]
    {
        new DeviceRetrievalMethod
        {
            Type = RetrievalType.BLE,
            Version = 1,
            RetrievalOptions = new { ble_peripheral_mode = true }
        }
    }
};

var qrCode = deviceEngagement.ToQrCodeData();

Custom mdoc Document Types

// Define custom mdoc type (e.g., employee badge)
var employeeBadge = new MdocClaims
{
    DocType = "com.example.employee.1",
    Namespace = "com.example.employee",
    Claims = new Dictionary<string, object>
    {
        ["employee_id"] = "E12345",
        ["full_name"] = "Jane Doe",
        ["department"] = "Engineering",
        ["clearance_level"] = "Secret",
        ["badge_photo"] = photoBytes,
        ["valid_from"] = "2024-01-01",
        ["valid_until"] = "2025-01-01"
    }
};

var employeeCredential = await issuer.IssueAsync(employeeBadge);

Batch Issuance

// Issue multiple mdocs efficiently
var mdocBatch = new[]
{
    mdlClaims,
    passportClaims,
    healthCardClaims
};

var issuedDocs = await issuer.IssueBatchAsync(mdocBatch);

Console.WriteLine($"Issued {issuedDocs.Count} documents");

Platform Support

  • .NET 8, 9, 10: Full support with latest optimizations
  • .NET Standard 2.1: Cross-platform compatibility
  • Windows: Full proximity (QR, NFC, BLE) support
  • Linux: QR code and BLE support
  • macOS: QR code and BLE support
  • iOS/Android: Via MAUI with native proximity APIs

Specifications

This package implements:

Contributing

See CONTRIBUTING.md for development guidelines.

License

Apache 2.0 - See LICENSE.txt

Support

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on SdJwt.Net.Mdoc:

Package Downloads
SdJwt.Net.Eudiw

EU Digital Identity Wallet (EUDIW) profile implementation for the SD-JWT .NET ecosystem. Provides eIDAS 2.0 compliance, ARF validation, EU Trust List integration, PID credential handling, and QEAA/EAA support for European digital identity verification.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 37 3/13/2026
1.0.1 108 3/1/2026