nMRTD 0.4.1-alpha
dotnet add package nMRTD --version 0.4.1-alpha
NuGet\Install-Package nMRTD -Version 0.4.1-alpha
<PackageReference Include="nMRTD" Version="0.4.1-alpha" />
<PackageVersion Include="nMRTD" Version="0.4.1-alpha" />
<PackageReference Include="nMRTD" />
paket add nMRTD --version 0.4.1-alpha
#r "nuget: nMRTD, 0.4.1-alpha"
#:package nMRTD@0.4.1-alpha
#addin nuget:?package=nMRTD&version=0.4.1-alpha&prerelease
#tool nuget:?package=nMRTD&version=0.4.1-alpha&prerelease
nMRTD
Status: THIS IS AN EARLY-STAGE PORT: the core protocol stack (BAC, PACE, EAC, Active/Passive Authentication) and the LDS/biometric data model are implemented and build cleanly, but the library has not yet been exercised against a broad range of real-world documents or covered by an automated test suite. Treat it as a foundation to build on and validate for your own use case, not as a production-hardened SDK yet.
Please note: this project is AI-assisted.
nMRTD is a .NET 6/8 library for reading electronic Machine Readable Travel Documents (eMRTDs) — biometric passports, electronic ID cards, and similar ICAO-compliant documents — over NFC/contactless smart card readers, implementing the ICAO Doc 9303 specification.
It is a from-scratch C# port of JMRTD, the reference Java implementation of the MRTD standards, targeting .NET 6/8, Native AOT (.NET 8 only), and cross-platform smart card access (Windows, Linux, macOS) via PC/SC.
Features
- Smart card access layer — a
CardServiceabstraction (command/response APDUs, file system, TLV utilities) with a cross-platform PC/SC implementation (PCSC/PCSC.Iso7816) working over WinSCard on Windows and PC/SC-lite on Linux/macOS. - Access-control and secure-messaging protocols:
- BAC (Basic Access Control), keyed from the MRZ.
- PACE (Password Authenticated Connection Establishment), keyed either from the MRZ or from the document's CAN (Card Access Number).
- EAC (Extended Access Control): Chip Authentication and Terminal Authentication (BSI TR-03110), including Card Verifiable (CV) certificate parsing/building.
- Active Authentication.
- Secure Messaging (DESede and AES) wrapping every subsequent APDU exchange.
- LDS (Logical Data Structure) parsing — EF.COM, EF.SOD, and data groups DG1 through DG16 (MRZ, facial/fingerprint/iris images, additional personal/document details, security infos, and more), plus Passive Authentication: verifying each data group's hash and the EF.SOD's CMS/PKCS#7 signature.
- Biometric data models for both ISO/IEC 19794 (face/finger/iris, the common case) and the newer ISO/IEC 39794 standard, wrapped per CBEFF (ISO/IEC 7816-11).
- Native AOT and trimming friendly, with no reflection-based dispatch or serialization — built to publish as a self-contained native executable on any of the supported platforms.
Installation
Add the package to your .NET project:
dotnet add package nMRTD
or reference it directly in your .csproj:
<ItemGroup>
<PackageReference Include="nMRTD" />
</ItemGroup>
nMRTD targets .NET 6/8 and depends on the following transitive dependencies:
BouncyCastle.Cryptography(crypto/ASN.1)PCSCPCSC.Iso7816(smart card access)
Quick start
Reading a document with BAC
using nMRTD;
using nMRTD.Lds.Icao;
using nMRTD.SmartCards;
// Connect to the first available PC/SC reader.
var cardService = new PcscCardService();
var passportService = new PassportService(
cardService,
PassportService.NormalMaxTranceiveLength,
PassportService.DefaultMaxBlocksize,
isSfiEnabled: true,
shouldCheckMac: true);
passportService.Open();
// Authenticate with Basic Access Control, keyed from the printed MRZ.
var bacKey = new BacKey(
documentNumber: "L898902C3",
dateOfBirth: "740812", // yyMMdd
dateOfExpiry: "120415"); // yyMMdd
passportService.SendSelectApplet(false);
passportService.DoBAC(bacKey);
// Read and parse EF.DG1 (the MRZ).
using Stream dg1Stream = passportService.GetInputStream(PassportService.EF_DG1);
var dg1 = new DG1File(dg1Stream);
Console.WriteLine($"Document number: {dg1.GetMRZInfo().GetDocumentNumber()}");
// Read and parse EF.DG2 (the facial image).
using Stream dg2Stream = passportService.GetInputStream(PassportService.EF_DG2);
var dg2 = new DG2File(dg2Stream);
passportService.Close();
Authenticating with PACE, via MRZ or CAN
Most current documents advertise PACE support in EF.CardAccess; prefer it over BAC when available:
using nMRTD;
using nMRTD.Lds;
using nMRTD.SmartCards;
using Stream cardAccessStream = passportService.GetInputStream(PassportService.EF_CARD_ACCESS);
var cardAccessFile = new CardAccessFile(cardAccessStream);
PACEInfo paceInfo = cardAccessFile.GetSecurityInfos().OfType<PACEInfo>().First();
var parameterId = paceInfo.GetParameterId()!;
object staticParameters = PACEInfo.ToParameterSpec(parameterId);
// Option A -- derive the PACE key from the MRZ, same details as for BAC:
IAccessKeySpec paceKey = PaceKeySpec.CreateMrzKey(
new BacKey("L898902C3", "740812", "120415"));
// Option B -- derive the PACE key from the Card Access Number printed on the
// document instead. A CAN can *only* be used for PACE, never for BAC.
// IAccessKeySpec paceKey = PaceKeySpec.CreateCanKey("500540");
passportService.DoPace(paceKey, paceInfo.GetObjectIdentifier(), staticParameters, parameterId);
passportService.SendSelectApplet(true);
// From here on, read DG1/DG2/... exactly as in the BAC example above.
For a complete, runnable example covering reader selection, PACE-with-BAC-fallback, DG1/DG2 parsing, and full Passive Authentication (EF.SOD hash and signature verification), see nMRTD.Cli/Program.cs in this repository.
License
nMRTD is a derivative work: a from-scratch C# port of JMRTD, originally written in Java by the JMRTD team. All credit for the original design, protocol implementation, and years of ICAO 9303 domain expertise belongs to them; this project would not exist without their work. nMRTD is not affiliated with or endorsed by the JMRTD project.
Like its upstream, nMRTD is distributed under the terms of the GNU Lesser General Public License v3 (LGPL-3.0). See the LICENSE file for the full license text.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. 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 was computed. 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 was computed. 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. |
-
net6.0
- BouncyCastle.Cryptography (>= 2.6.2)
- PCSC (>= 7.0.1)
- PCSC.Iso7816 (>= 7.0.1)
-
net8.0
- BouncyCastle.Cryptography (>= 2.6.2)
- PCSC (>= 7.0.1)
- PCSC.Iso7816 (>= 7.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.4.1-alpha | 67 | 9/1/2026 |
| 0.4.0-alpha | 61 | 9/1/2026 |
| 0.3.0-alpha | 71 | 8/26/2026 |
| 0.2.0-alpha | 67 | 8/23/2026 |