libthai-idcard 0.2.0

A Rust library for reading Thai National ID smart cards via PC/SC
Documentation
> **๐ŸŒ Language:** English ยท [เน„เธ—เธข]README.th.md

# libthai-idcard

[![Crates.io](https://img.shields.io/crates/v/libthai-idcard)](https://crates.io/crates/libthai-idcard)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue)](https://github.com/phakhawatchu/libthai-idcard)
[![CI](https://github.com/phakhawatchu/libthai-idcard/actions/workflows/ci.yml/badge.svg)](https://github.com/phakhawatchu/libthai-idcard/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/phakhawatchu/libthai-idcard?logo=github)](https://github.com/phakhawatchu/libthai-idcard/releases/latest)
[![MSRV](https://img.shields.io/badge/rustc-1.81%2B-lightgrey)](https://github.com/phakhawatchu/libthai-idcard)

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

```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:

```rust
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`](examples/rust_usage.rs) for a complete example.

### C

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

```bash
# 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`](examples/cpp_usage.cpp).
It uses RAII wrappers and C++17 features to load the shared library
and read card data.

```bash
# 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`](examples/go_usage.go).
It uses `cgo` to load the shared library via `dlopen` and read card data.

```bash
go run examples/go_usage.go
```

### Java

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

```bash
# 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`](examples/kotlin_usage.kt).
It uses **JNA** (Java Native Access) to call the shared library functions.

```bash
# 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`](examples/js_usage.js).
It uses **koffi** (a modern FFI library for Node.js) to call the shared
library functions.

```bash
npm install koffi
node examples/js_usage.js
```

### Python

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

```bash
python3 examples/python_usage.py
```

### Ruby

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

```bash
ruby examples/ruby_usage.rb
```

## Building

```bash
# 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](https://github.com/phakhawatchu/libthai-idcard/releases/latest)
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.

```bash
# 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]#pre-built-binaries from GitHub Releases, built natively
> on GitHub Actions runners.

Or directly with Cargo:

```bash
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

- [Thai National ID Card APDU Specification]https://github.com/chakphanu/ThaiNationalIDCard/blob/master/APDU.md
- [go-thai-smartcard NHSO APDU Implementation]https://github.com/somprasongd/go-thai-smartcard/blob/main/pkg/apdu/nhso.go

## License

Licensed under either of:

- MIT license ([LICENSE-MIT]LICENSE-MIT)
- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE)

at your option.