@huitl/sdk
v0.3.1
Published
NTAG 424 DNA cryptographic verification SDK — parse, decrypt, and verify NFC SUN messages
Maintainers
Readme
@huitl/sdk
Built by HUITL Protocol — the open verification standard for physical objects.
HUITL Protocol proves physical objects are real using standard NFC chips. Every tap produces a unique, one-time cryptographic signature that can never be replicated or reused. This SDK is the core of the protocol — MIT-licensed, zero runtime dependencies, production-ready.
The cheapest, simplest path from NFC chip tap to cryptographic proof. Standard hardware. Open protocol. Developer-first.
Created by Fabio Seva — founder of HUITL Protocol.
For questions, partnerships, or enterprise inquiries: [email protected]
Use Cases & Templates
| Use Case | Description | Template | Status |
|----------|-------------|----------|--------|
| Product Authentication | Luxury goods, pharma, wine & spirits, electronics | huitl-template-auth | Live |
| Digital Product Passport | EU DPP compliance (batteries Feb 2027, textiles 2027) | huitl init --template dpp | Coming soon |
| Ticketing & Membership | Event tickets and membership cards that can't be duplicated | huitl init --template ticketing | Coming soon |
| Proof of Presence | Retail, events, tourist sites — no GPS spoofing possible | huitl init --template presence | Coming soon |
| Anti-Counterfeiting | Supply chain verification at every touchpoint | huitl init --template anti-counterfeit | Coming soon |
Try It Now
No chips, no hardware, no setup:
npm install -g @huitl/sdk
huitl verify "https://huitlprotocol.com/tap?picc_data=2C309D265CFFD369A4B62C6B9F40B669&cmac=6A6595D519DF58BF" --key 00000000000000000000000000000000{ "valid": true, "uid": "04112233445566", "readCounter": 42 }That's a real cryptographic verification — the same math that runs on every NFC tap. The URL contains an encrypted chip identity and a one-time signature. The SDK decrypts, derives a session key, and validates the CMAC.
Installation
npm install @huitl/sdkQuick Start
import { parseSunMessage, verifySun } from "@huitl/sdk";
// When a user taps an NFC chip, their phone opens a URL like:
// https://yourapp.com/tap?picc_data=EF963FF7828658A599F3041510671E88&cmac=94EED9EE65337086
const sdmKey = Buffer.from("00000000000000000000000000000000", "hex");
const tapUrl = "https://yourapp.com/tap?picc_data=EF963FF7...&cmac=94EED9EE...";
const parsed = parseSunMessage(tapUrl);
const result = verifySun(sdmKey, parsed.encPiccData, parsed.cmac, parsed.macInput);
console.log(result);
// { valid: true, uid: "04112233445566", readCounter: 42 }API Reference
parseSunMessage(url: string): SunMessage
Parse a SUN message URL from an NTAG 424 DNA chip tap.
const { encPiccData, cmac, macInput } = parseSunMessage(url);verifySun(sdmKey, encPiccData, cmac, macInput): VerifyResult
Full end-to-end SUN verification: decrypts PICC data, derives session key, computes and compares CMAC using crypto.timingSafeEqual.
const result = verifySun(sdmKey, encPiccData, cmac, macInput);
// { valid: boolean, uid: string, readCounter: number }decryptPiccData(key: Buffer, enc: Buffer): PiccData
Decrypt encrypted PICC data (AES-128-CBC, zero IV) to extract the chip UID and read counter.
deriveSessionKey(sdmKey, uid, counter, isMac): Buffer
Derive a session key for SDM MAC or ENC operations per NXP AN12196.
aesCmac(key: Buffer, msg: Buffer): Buffer
Compute AES-CMAC per RFC 4493.
CLI
huitl verify <url> --key <hex>
Verify a SUN message URL. Outputs JSON, exits 0 if valid.
huitl verify "https://example.com/tap?picc_data=...&cmac=..." --key 00000000000000000000000000000000huitl keygen [--count N]
Generate random AES-128 key + UID pairs for testing.
huitl keygen
# { "uid": "04A1B2C3D4E5F6", "aesKey": "1234567890ABCDEF1234567890ABCDEF" }
huitl keygen --count 5
# [ { "uid": "...", "aesKey": "..." }, ... ]huitl dev --local
Start a local development server with SQLite for testing NFC verification.
huitl dev --local
# Server running at http://localhost:3000
# Tap URL: http://localhost:3000/tap?picc_data=<32hex>&cmac=<16hex>Endpoints:
GET /tap?picc_data=...&cmac=...— Verify a tapGET /api/chips— List registered test chipsPOST /api/chips— Register a test chip{ "uid": "...", "aesKey": "...", "name": "..." }
huitl provision
Provision an NTAG 424 DNA chip — writes AES key + SUN configuration.
Requirements: PC/SC compatible NFC reader + npm install -g nfc-pcsc
With HUITL Cloud (default):
huitl login --api-key <your-key>
huitl provision --name "My Product"
# Place chip on reader → doneLocal mode:
huitl provision --local --key 00000000000000000000000000000000Browser UI (batch provisioning):
huitl provision --ui
# Opens http://localhost:4000 — provision chips with a visual interface
# Auto-increment naming, session history, CSV exporthuitl login
Authenticate with HUITL Cloud.
# Get your API key at https://huitl-cloud.vercel.app/api/auth/google
huitl login --api-key <your-key>huitl init [directory]
Scaffold a new HUITL project from a starter template.
huitl init my-app
cd my-app && npm installSupported NFC Readers
| Reader | USB | Price | Notes | |--------|-----|-------|-------| | ACR122U | USB-A | ~$25 | Most common, recommended | | ACR1252U | USB-C | ~$35 | USB-C version | | HID OMNIKEY 5022 | USB-A | ~$40 | Enterprise-grade | | Identiv uTrust 3700F | USB-A | ~$45 | Also supports HF |
Does NOT work: RC522 (SPI, no APDU), phone NFC (no raw APDU on iOS), UID-only readers.
Types
interface PiccData {
uid: string; // 7-byte UID as uppercase hex
readCounter: number; // SDM read counter
}
interface VerifyResult {
valid: boolean;
uid: string;
readCounter: number;
}
interface SunMessage {
encPiccData: Buffer; // Encrypted PICC data (16 bytes)
cmac: Buffer; // Truncated CMAC (8 bytes)
macInput: Buffer; // URL portion used as MAC input
}How It Works
- An NTAG 424 DNA chip is configured with an AES-128 key and SUN (Secure Unique NFC) messaging
- When tapped, the chip produces a URL containing encrypted PICC data and a CMAC signature
- The PICC data contains the chip's unique 7-byte UID and a rolling read counter
- A session key is derived from the SDM key, UID, and counter
- The CMAC is computed over the URL content using the session key
- Verification checks: correct decryption, valid CMAC, and counter increment (anti-replay)
Each tap produces a unique, cryptographically bound message that cannot be replicated or replayed.
Architecture
┌──────────────────────────────────────┐
│ Your Application │
└──────────────────┬───────────────────┘
│ uses
┌──────────────────▼───────────────────┐
│ @huitl/sdk │
│ parseSunMessage() │ verifySun() │
│ decryptPiccData() │ deriveSessionKey │
│ aesCmac() │ TypeScript types │
│ MIT Licensed │
└──────────────────────────────────────┘HUITL Ecosystem
| Repo | Description | |------|-------------| | @huitl/sdk | Open-source SDK + CLI (this repo) | | HUITL Cloud | Key registry + verification API | | Template: Auth | Product authentication with ownership |
Contributing
See CONTRIBUTING.md.
License
MIT
