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 |
| OpenPGP | 3B DA … | YubiKey, GPG operations |
| PKCS#15 | 3B 9F … | Generic PKI, e-signing |
see also
- Web Smart Card API — feature index
- ChromeStatus entry
- Spec