libthai-idcard 0.2.0

A Rust library for reading Thai National ID smart cards via PC/SC
Documentation

๐ŸŒ Language: English ยท เน„เธ—เธข

libthai-idcard

Crates.io License CI Release MSRV

A Rust library for reading Thai National ID smart cards via PC/SC smart card readers, with C, C++, Go, Java, Kotlin, JavaScript, Python, and Ruby usage examples.

Overview

Thai National ID smart cards store citizen identification data, a JPEG face photo, NHSO (National Health Security Office) insurance information, and a laser-engraved card serial number. This library handles the low-level APDU communication, TIS-620 (Thai) text decoding, and Buddhist-to-Gregorian date conversion, exposing the data through a clean multi-language API.

Features

  • โœ… Read citizen ID, name (Thai & English), date of birth, gender
  • โœ… Read registered address (parsed into components)
  • โœ… Read card issuer, issue date, expiry date
  • โœ… Read JPEG face photo (returned as base64)
  • โœ… Read laser-engraved card serial number
  • โœ… Read NHSO insurance data (main/sub hospitals, coverage dates, etc.)
  • โœ… Buddhist year โ†’ Gregorian calendar conversion
  • โœ… TIS-620 (Windows-874) Thai text decoding
  • โœ… Auto-detect card reader or specify by name
  • โœ… Daemon mode for continuous card monitoring
  • โœ… C usage example (dynamic loading or link-time)
  • โœ… C++ usage example (via dlopen/LoadLibrary)
  • โœ… Go usage example (via cgo)
  • โœ… Java usage example (via JNA)
  • โœ… Kotlin usage example (via JNA)
  • โœ… JavaScript usage example (via koffi)
  • โœ… Python usage example (via ctypes)
  • โœ… Ruby usage example (via fiddle)

Requirements

  • Hardware: A PC/SC-compatible smart card reader and a Thai National ID card
  • Software: PC/SC Lite (pcsclite) โ€” installed by default on macOS and most Linux distributions
    • macOS: Built-in (PCSC.framework)
    • Linux: sudo apt install libpcsclite-dev (Debian/Ubuntu) or sudo dnf install pcsc-lite-devel (Fedora)
    • Windows: Winscard (built-in)

Usage

Rust

use thaiidcard::{SmartCard, Options};

let card = SmartCard::new();
let data = card.read(None, &Options::default()).unwrap();

let personal = data.personal.unwrap();
println!("Name: {}", personal.name.full_name);
println!("CID: {}", personal.cid);
println!("DOB: {}", personal.dob);

Or with a specific reader and extra data sections:

use thaiidcard::{SmartCard, Options};

let opts = Options {
    show_nhso_data: true,
    show_laser_data: true,
    show_face_image: true,
    ..Default::default()
};

let card = SmartCard::new();
let data = card.read(Some("Identive USB Reader"), &opts).unwrap();

See examples/rust_usage.rs for a complete example.

C

A C usage example is available at examples/c_usage.c. It demonstrates both dynamic loading (dlopen/dlsym) and compile-time linking against the shared library.

# Dynamic loading (no linker flags)
cc -o c_usage examples/c_usage.c -ldl
./c_usage

# Compile-time linking
cc -o c_usage examples/c_usage.c -Ltarget/debug -lthaiidcard \
   -lpcsclite -Wl,-rpath,target/debug
./c_usage

C++

A C++ usage example is available at examples/cpp_usage.cpp. It uses RAII wrappers and C++17 features to load the shared library and read card data.

# macOS / Linux:
g++ -std=c++17 -o cpp_usage examples/cpp_usage.cpp -ldl
./cpp_usage

# Windows (MinGW):
g++ -std=c++17 -o cpp_usage.exe examples/cpp_usage.cpp
./cpp_usage

Go

A Go usage example is available at examples/go_usage.go. It uses cgo to load the shared library via dlopen and read card data.

go run examples/go_usage.go

Java

A Java usage example is available at examples/java_usage.java. It uses JNA (Java Native Access) to call the shared library functions.

# With jbang (auto-downloads JNA):
jbang examples/java_usage.java

# Or compile & run manually (download jna.jar first):
javac -cp jna.jar examples/java_usage.java
java -cp .:jna.jar java_usage

Kotlin

A Kotlin usage example is available at examples/kotlin_usage.kt. It uses JNA (Java Native Access) to call the shared library functions.

# With jbang (auto-downloads JNA):
jbang examples/kotlin_usage.kt

# Or compile & run manually (download jna.jar first):
kotlinc -cp jna.jar examples/kotlin_usage.kt
kotlin -cp .:jna.jar kotlin_usageKt

JavaScript

A JavaScript usage example is available at examples/js_usage.js. It uses koffi (a modern FFI library for Node.js) to call the shared library functions.

npm install koffi
node examples/js_usage.js

Python

A Python usage example is available at examples/python_usage.py. It uses ctypes to load the shared library and read card data.

python3 examples/python_usage.py

Ruby

A Ruby usage example is available at examples/ruby_usage.rb. It uses fiddle (Ruby's built-in FFI library) to load the shared library and read card data.

ruby examples/ruby_usage.rb

Building

# Build all Rust targets (library + examples)
make build

# Build only the native shared library (.dylib/.so/.dll)
make shared

# Generate C header file (requires cbindgen)
make headers

# Run the Rust usage example
make example

# Run the C example
make c-example

# Run the C++ example
make cpp-example

# Run the Go example
make go-example

# Run the Java example
make java-example

# Run the Kotlin example
make kotlin-example

# Run the JavaScript example
make js-example

# Run the Python example
make python-example

# Run the Ruby example
make ruby-example

Pre-built Binaries

Pre-built shared libraries are available on the GitHub Releases page for the following platforms:

Platform Architecture File
Linux x86_64 libthaiidcard-linux-x86_64.so
Linux ARM64 libthaiidcard-linux-arm64.so
macOS x86_64 (Intel) libthaiidcard-macos-x86_64.dylib
macOS ARM64 (Apple Silicon) libthaiidcard-macos-arm64.dylib
Windows x86_64 thaiidcard-windows-x86_64.dll
Windows ARM64 thaiidcard-windows-arm64.dll

Cross-compilation

All cross-compilation targets use Docker (except build-win-native* which require a locally installed mingw-w64). macOS builds use osxcross to provide the Apple SDK and toolchain inside the Linux-based Docker image.

# Build Linux .so via Docker (x86_64)
make build-linux

# Build Linux .so via Docker (ARM64)
make build-linux-arm64

# Build macOS .dylib via Docker using osxcross (Intel)
make build-mac-x64

# Build macOS .dylib via Docker using osxcross (Apple Silicon)
make build-mac

# Build Windows DLL via Docker (x86_64)
make build-win

# Build Windows DLL natively (x86_64, requires mingw-w64)
make build-win-native

# Build Windows DLL natively in release mode
make build-win-native-release

Note: Windows ARM64 and Linux ARM64 builds are also available as pre-built binaries from GitHub Releases, built natively on GitHub Actions runners.

Or directly with Cargo:

cargo build --release
cargo build --lib # shared library only

Data Model

CardData
โ”œโ”€โ”€ personal: Personal
โ”‚   โ”œโ”€โ”€ cid              โ€” 13-digit citizen ID
โ”‚   โ”œโ”€โ”€ name             โ€” Full name in Thai (with prefix, first, middle, last)
โ”‚   โ”œโ”€โ”€ name_en          โ€” Full name in English
โ”‚   โ”œโ”€โ”€ dob              โ€” Date of birth (YYYY-MM-DD)
โ”‚   โ”œโ”€โ”€ gender           โ€” M or F
โ”‚   โ”œโ”€โ”€ card_issuer      โ€” Issuing authority
โ”‚   โ”œโ”€โ”€ issue_date       โ€” Card issue date (YYYY-MM-DD)
โ”‚   โ”œโ”€โ”€ expire_date      โ€” Card expiry date (YYYY-MM-DD)
โ”‚   โ”œโ”€โ”€ address          โ€” Registered address (parsed into components)
โ”‚   โ””โ”€โ”€ face_image       โ€” Face photo as base64 JPEG
โ”œโ”€โ”€ card: Card
โ”‚   โ””โ”€โ”€ laser_id         โ€” Laser-engraved serial number
โ””โ”€โ”€ nhso: Nhso
      โ”œโ”€โ”€ main_inscl     โ€” Main insurance scheme
      โ”œโ”€โ”€ sub_inscl      โ€” Sub insurance scheme
      โ”œโ”€โ”€ main_hospital  โ€” Primary hospital
      โ”œโ”€โ”€ sub_hospital   โ€” Secondary hospital
      โ”œโ”€โ”€ paid_type      โ€” Payment type
      โ”œโ”€โ”€ issue_date     โ€” NHSO coverage start date
      โ”œโ”€โ”€ expire_date    โ€” NHSO coverage end date
      โ”œโ”€โ”€ update_date    โ€” Last update date
      โ””โ”€โ”€ change_hospital_amount โ€” Hospital change count

Project Structure

โ”œโ”€โ”€ Cargo.toml
โ”œโ”€โ”€ Makefile
โ”œโ”€โ”€ Dockerfile.build       โ€” Cross-compilation Docker image (osxcross)
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ lib.rs             โ€” Main API (SmartCard, start_daemon)
โ”‚   โ”œโ”€โ”€ ffi.rs             โ€” C-compatible FFI exports
โ”‚   โ”œโ”€โ”€ model.rs           โ€” Data types & parsing helpers
โ”‚   โ”œโ”€โ”€ apdu.rs            โ€” APDU command constants
โ”‚   โ”œโ”€โ”€ reader.rs          โ€” Low-level PC/SC operations
โ”‚   โ”œโ”€โ”€ personal.rs        โ€” Personal data reader
โ”‚   โ”œโ”€โ”€ nhso.rs            โ€” NHSO data reader
โ”‚   โ”œโ”€โ”€ laser.rs           โ€” Laser ID reader
โ”‚   โ””โ”€โ”€ options.rs         โ€” Configuration options
โ””โ”€โ”€ examples/
    โ”œโ”€โ”€ rust_usage.rs      โ€” Rust usage example
    โ”œโ”€โ”€ c_usage.c          โ€” C usage example
    โ”œโ”€โ”€ cpp_usage.cpp      โ€” C++ usage example
    โ”œโ”€โ”€ go_usage.go        โ€” Go usage example
    โ”œโ”€โ”€ java_usage.java    โ€” Java usage example
    โ”œโ”€โ”€ kotlin_usage.kt    โ€” Kotlin usage example
    โ”œโ”€โ”€ js_usage.js        โ€” JavaScript usage example
    โ”œโ”€โ”€ python_usage.py    โ€” Python usage example
    โ””โ”€โ”€ ruby_usage.rb      โ€” Ruby usage example

References

License

Licensed under either of:

at your option.