# @animo-id/mdoc

> Animo Mdoc and MDL

Latest version **0.5.2** (published 2025-03-22) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install @animo-id/mdoc
pnpm add @animo-id/mdoc
yarn add @animo-id/mdoc
bun add @animo-id/mdoc
```

## Health

**Score 55/100 (C)** — status: stable.

Positive: has types; esm support; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 0.5.2 |
| Published | 2025-03-22 |
| First published | 2024-11-19 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 1 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 13 |
| Author | Martin Auer |
| Maintainers | blu3beri, timoglastra, animo-ana, animo-bot |
| Keywords | mdl, iso-18013-5, iso-18013-7, m-doc, m-doc-cbor, m-doc-cbor-parser, m-doc-cbor-validator, m-doc-cbor-encoder, m-doc-cbor-decoder, m-doc-cbor-iso-18013-5, m-doc-cbor-iso-18013-5-parser, m-doc-cbor-iso-18013-5-validator, m-doc-cbor-iso-18013-5-encoder, m-doc-cbor-iso-18013-5-decoder |

## Links

- npm: https://www.npmjs.com/package/@animo-id/mdoc
- Repository: https://github.com/animo/mdoc
- Homepage: https://github.com/animo/mdoc#readme
- Issues: https://github.com/animo/mdoc/issues
- npm.io page: https://npm.io/package/@animo-id/mdoc

## Dependencies (1)

- [compare-versions](https://npm.io/package/compare-versions.md) ^6.1.1

## Alternatives

- [flatbuffers](https://npm.io/package/flatbuffers.md) — 6.0M weekly downloads
- [jwt-simple](https://npm.io/package/jwt-simple.md) — 259.5K weekly downloads
- [@exodus/patch-broken-hermes-typed-arrays](https://npm.io/package/@exodus/patch-broken-hermes-typed-arrays.md) — 28.5K weekly downloads
- [@native-to-anchor/buffer-layout](https://npm.io/package/@native-to-anchor/buffer-layout.md) — 12.2K weekly downloads
- [binary-parser-encoder](https://npm.io/package/binary-parser-encoder.md) — 5.3K weekly downloads

## Recent versions

- 0.5.2 (latest) — 2025-03-22
- 0.6.0-alpha-20260202121208 (alpha) — 2026-02-02
- 0.6.0-alpha-20260129172419 — 2026-01-29
- 0.6.0-alpha-20260126144751 — 2026-01-26
- 0.6.0-alpha-20260126082455 — 2026-01-26
- 0.6.0-alpha-20260120161117 — 2026-01-20
- 0.6.0-alpha-20260119192037 — 2026-01-19
- 0.6.0-alpha-20251209053057 — 2025-12-09
- 0.6.0-alpha-20251209052411 — 2025-12-09
- 0.6.0-alpha-20251201102501 — 2025-12-01
- 0.6.0-alpha-20251127093633 — 2025-11-27
- 0.6.0-alpha-20251127043831 — 2025-11-27
- 0.6.0-alpha-20251127040407 — 2025-11-27
- 0.6.0-alpha-20251121153050 — 2025-11-21
- 0.6.0-alpha-20251121152551 — 2025-11-21
- … 55 more at https://npm.io/package/@animo-id/mdoc/versions

## README

<p align="center">
  <picture>
   <source media="(prefers-color-scheme: light)" srcset="https://res.cloudinary.com/animo-solutions/image/upload/v1656578320/animo-logo-light-no-text_ok9auy.svg">
   <source media="(prefers-color-scheme: dark)" srcset="https://res.cloudinary.com/animo-solutions/image/upload/v1656578320/animo-logo-dark-no-text_fqqdq9.svg">
   <img alt="Animo Logo" height="250px" />
  </picture>
</p>

<h1 align="center" ><b>mDOC and mDL - TypeScript</b></h1>

[ISO 18013-5](https://www.iso.org/standard/69084.html) defines mDL (mobile Driver’s Licenses): an ISO standard for digital driver licenses.

This is a JavaScript library for Node.JS, browers and React Native to issue and verify mDL [CBOR encoded](https://cbor.io/) documents in accordance with **ISO 18013-7 (draft's date: 2024-03-12)**.

<h4 align="center">Powered by &nbsp; 
  <picture>
    <source media="(prefers-color-scheme: light)" srcset="https://res.cloudinary.com/animo-solutions/image/upload/v1656579715/animo-logo-light-text_cma2yo.svg">
    <source media="(prefers-color-scheme: dark)" srcset="https://res.cloudinary.com/animo-solutions/image/upload/v1656579715/animo-logo-dark-text_uccvqa.svg">
    <img alt="Animo Logo" height="12px" />
  </picture>
</h4><br>

<p align="center">
  <a href="https://typescriptlang.org">
    <img src="https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg" />
  </a>
</p>

<p align="center">
  <a href="#installation">Installation</a> 
  &nbsp;|&nbsp;
  <a href="#usage">Usage</a> 
  &nbsp;|&nbsp;
  <a href="#contributing">Contributing</a>
  &nbsp;|&nbsp;
  <a href="#license">License</a>
  &nbsp;|&nbsp;
  <a href="#credits">Credits</a>
</p>

## Installation

```bash
npm i @animo-id/mdoc
```

## Usage

### Verifying a credential

```javascript
import { Verifier } from "@animo-id/mdoc";
import { inspect } from "node:util";
import fs from "node:fs";

(async () => {
  const encodedDeviceResponse = Buffer.from(encodedDeviceResponseHex, "hex");
  const encodedSessionTranscript = Buffer.from(
    encodedSessionTranscriptHex,
    "hex"
  );
  const ephemeralReaderKey = Buffer.from(ephemeralReaderKeyHex, "hex");

  const trustedCerts = [fs.readFileSync("./caCert1.pem") /*, ... */];
  const verifier = new Verifier(trustedCerts);
  const mdoc = await verifier.verify(encodedDeviceResponse, {
    ephemeralReaderKey,
    encodedSessionTranscript,
  });

  //at this point the issuer and device signature are valids.
  inspect(mdoc);
})();
```

### Getting diagnostic information

```javascript
import { Verifier } from "@animo-id/mdoc";
import { inspect } from "node:util";
import fs from "node:fs";

(async () => {
  const encodedDeviceResponse = Buffer.from(encodedDeviceResponseHex, "hex");
  const encodedSessionTranscript = Buffer.from(
    encodedSessionTranscriptHex,
    "hex"
  );
  const ephemeralReaderKey = Buffer.from(ephemeralReaderKeyHex, "hex");

  const trustedCerts = [fs.readFileSync("./caCert1.pem") /*, ... */];
  const verifier = new Verifier(trustedCerts);

  const diagnosticInfo = await verifier.getDiagnosticInformation(
    encodedDeviceResponse,
    {
      ephemeralReaderKey,
      encodedSessionTranscript,
    }
  );

  inspect(diagnosticInfo);
})();
```

##$ Issuing a credential

```js
import { MDoc, Document } from "@animo-id/mdoc";
import { inspect } from "node:util";

(async () => {
  const document = await new Document("org.iso.18013.5.1.mDL")
    .addIssuerNameSpace("org.iso.18013.5.1", {
      family_name: "Jones",
      given_name: "Ava",
      birth_date: "2007-03-25",
    })
    .useDigestAlgorithm("SHA-256")
    .addValidityInfo({
      signed: new Date(),
    })
    .addDeviceKeyInfo({ deviceKey: publicKeyJWK })
    .sign({
      issuerPrivateKey,
      issuerCertificate,
    });

  const mdoc = new MDoc([document]).encode();

  inspect(encoded);
})();
```

##$ Generating a device response

```js
import { DeviceResponse, MDoc } from "@animo-id/mdoc";

(async () => {
  let issuerMDoc;
  let deviceResponseMDoc;

  /**
   * This is what the MDL issuer does to generate a credential:
   */
  {
    let issuerPrivateKey;
    let issuerCertificate;
    let devicePublicKey; // the public key for the device, as a JWK

    const document = await new Document("org.iso.18013.5.1.mDL")
      .addIssuerNameSpace("org.iso.18013.5.1", {
        family_name: "Jones",
        given_name: "Ava",
        birth_date: "2007-03-25",
      })
      .useDigestAlgorithm("SHA-256")
      .addValidityInfo({
        signed: new Date(),
      })
      .addDeviceKeyInfo({ deviceKey: devicePublicKey })
      .sign({
        issuerPrivateKey,
        issuerCertificate,
        alg: "ES256",
      });

    issuerMDoc = new MDoc([document]).encode();
  }

  /**
   * This is what the DEVICE does to generate a response...
   */
  {
    let devicePrivateKey; // the private key for the device, as a JWK

    // Parameters coming from the OID4VP transaction
    let mdocGeneratedNonce, clientId, responseUri, verifierGeneratedNonce;
    let presentationDefinition = {
      id: "family_name_only",
      input_descriptors: [
        {
          id: "org.iso.18013.5.1.mDL",
          format: { mso_mdoc: { alg: ["EdDSA", "ES256"] } },
          constraints: {
            limit_disclosure: "required",
            fields: [
              {
                path: ["$['org.iso.18013.5.1']['family_name']"],
                intent_to_retain: false,
              },
            ],
          },
        },
      ],
    };

    deviceResponseMDoc = await DeviceResponse.from(issuerMDoc)
      .usingPresentationDefinition(presentationDefinition)
      .usingSessionTranscriptForOID4VP(
        mdocGeneratedNonce,
        clientId,
        responseUri,
        verifierGeneratedNonce
      )
      .authenticateWithSignature(devicePrivateKey, "ES256")
      .sign();
  }
})();
```

## Contributing

Is there something you'd like to fix or add? Great, we love community
contributions! To get involved, please follow our [contribution guidelines](./CONTRIBUTING.md).

## License

This project is licensed under the Apache License Version 2.0 (Apache-2.0).

## Credits

Thanks to:

- [auth0/mdl](https://github.com/auth0-lab/mdl) for the mdl implementation on which this repository is based.
- [auer-martin](https://github.com/auer-martin) for removing node.js dependencies and providing a pluggable crypto interface

---
_Source: https://npm.io/package/@animo-id/mdoc · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
