Concepts
The mental model and glossary behind the CrypTag API. Read this once and the Examples will make sense at a glance.
Result Conventions
Encoder — every method returns a result object, with duration (ms) on tag operations:
{ success: true, data: { /* method-specific */ }, duration: 12 } // success{ success: false, error: { code, message, details } } // failureDecoder — decode* methods return the same unified shape as the encoder; the decoded payload is nested under data:
{ success: true, data: { cmacValid: true, uid: '04...', counter: 7, /* ... */ } } // authentic{ success: true, data: { cmacValid: false, uid: '04...', counter: 7, /* ... */ } } // ran, NOT authentic{ success: false, error: { code, message } } // hard failure (E400 / E600)success: true only means the decode ran — authenticity is result.data.cmacValid, so always
check it. A CMAC mismatch is not a success: false; it is success: true with data.cmacValid: false.
The decoder shares the encoder’s structured error object (code + message), so error handling is
symmetric across the SDK. Invalid arguments to the throwing methods (constructor, getKey,
updateKey, setKeys, setParameters, detectEncryptionMode) throw a ValidationError instead.
Every result is a discriminated union on success — in TypeScript, if (result.success) narrows to
data, and the else branch narrows to error:
data— the method’s payload; present on success (omitted only when a method returns no payload).duration— milliseconds; added on encoder tag operations only.error— present on failure, and always a plain object{ code, message, details? }: never anErrorinstance and never a stack trace, so it logs andJSON.stringifys identically.detailsis optional extra context (e.g. the originating tag status word or the offending field) and may be any serialisable value. Internally the SDK throws aCrypTagError/ValidationError, but that never leaks into a result.
Error Codes
error.code on a failure is one of these categories, shared by the encoder and decoder:
| Code | Category | When it happens |
|---|---|---|
E100 | Connection | Reader, card, or transport problem (no reader, no card, discovery failed) |
E200 | Authentication | Wrong key, MAC mismatch, permission denied, or auth temporarily blocked |
E300 | Command | A tag command did not complete (select, read/write, change key/settings) |
E400 | Validation | Bad argument, key configuration, or expired session (encoder + decoder) |
E500 | Unknown | Unmapped / unexpected error |
E600 | Decoding | A decode could not be completed — decoder only (malformed or undecodable data) |
When a failure originates at the tag, its ISO/NTAG424 status word (e.g. 911E,
919D, 91AE) is translated into one of the categories above with a descriptive message.
Access-Right Values
Read / write / change access parameters accept:
0–4— the key number required for that operation.'free'— open access, no authentication.'never'— the operation is permanently denied.
Key Numbers
0— application master key (required to change keys / configuration).1–4— application keys. By SDM convention, key 2 = meta read (PICCData), key 3 = file read (MAC / file data).
When diversify is enabled, the effective key is derived per-tag from the master
key + UID (AN10922), using the global system identifier and application ID
as diversification inputs.
File Numbers
1— Capability Container (CC).2— NDEF.3— Proprietary.
SDM Profiles
Secure Dynamic Messaging mirrors fresh, verifiable data into the tag’s URL on every tap.
- plain — UID, counter, and CMAC mirrored in cleartext in the URL.
- encrypted — PICCData (UID + counter) encrypted, plus a CMAC.
- full — encrypted PICCData and encrypted file data, plus a CMAC.
Authentication Modes
- EV2 — standard AES-128 mutual authentication.
- LRP — Leakage-Resilient Primitive; hardened against side-channel attacks. Enabling it is irreversible.
Communication Modes
The mode a file uses for command/response protection:
- plain — no cryptographic protection.
- mac — integrity via CMAC.
- full — AES-128 encryption with CMAC integrity.