demo · v141

Card Reader Simulator

A visual smart card reader with insert/eject animation, an APDU command picker, and full connection flow via navigator.smartCard.requestContext(). The page simulates the reader when the API is unavailable (IWA-only), so you can trace every step of the PIV/CAC handshake without hardware.

IWA context required navigator.smartCard is exposed only to Isolated Web Apps. In a plain web origin the probe reports missing and live reader access is unavailable. Use an IWA context with a physical reader to exercise the APDU flow.
probing navigator.smartCard…
PC/SC Reader

reader status

reader:
card state:empty
protocol:
ATR:

APDU commands

Connection log will appear here.

the connection flow

// 1. Obtain a PC/SC context (IWA only)
const ctx = await navigator.smartCard.requestContext();

// 2. Enumerate connected readers
const readers = await ctx.listReaders();

// 3. Connect to the first reader's card
const connection = await ctx.connect(readers[0], "shared", {
  preferredProtocols: ["t1", "t0"],
});
console.log("protocol:", connection.protocol); // "t1"

// 4. Build and transmit an APDU (SELECT PIV applet)
const selectPIV = new Uint8Array([
  0x00, 0xA4, 0x04, 0x00, 0x09,
  0xA0, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00
]);
const respBuf = await connection.transmit(selectPIV);
const resp = new Uint8Array(respBuf);
const sw1 = resp.at(-2), sw2 = resp.at(-1);
console.log("SW:", sw1.toString(16), sw2.toString(16)); // 90 00

// 5. Disconnect
await connection.disconnect("leave");

ATR card-type identification

The Answer to Reset (ATR) is the first thing a card sends after power-up. Historic bytes in the ATR identify the card OS and applets. Common patterns:

Card Type ATR prefix Use
PIV (FIPS 201)3B D5 …US gov employee ID, signing
CAC (DoD)3B F9 …Military ID, VPN auth
OpenPGP3B DA …YubiKey, GPG operations
PKCS#153B 9F …Generic PKI, e-signing

see also