OpenEPCIS Data Carrier Authentication Vocabulary

Metadata about the physical data carrier of a serialised item, carried on EPCIS events: sealed authentication keys at reservation, the chip identity at encoding, and the verdict of every authenticated scan as an inspecting OBSERVE event. NTAG 424 DNA Secure Unique NFC today; RAIN RFID and signed QR reserved.

Version 0.9.9https://ref.openepcis.org/extensions/common/carrier/
Community implementation - not official GS1 guidance

This vocabulary builds on GS1 standards (Digital Link, EPCIS 2.0, Web Vocabulary) but extends them with properties not yet defined by GS1. The GS1 DPP Provisional Standard is still under development. Our extensions may be superseded by official GS1 terms as they emerge. Feedback welcome!

About this vocabulary

A GS1 identifier says which item a label stands for; it does not say that the label in front of you is the one that was issued. Secure NFC chips such as NXP's NTAG 424 DNA close that gap in hardware: every tap mirrors encrypted chip data and a message authentication code (Secure Unique NFC, SUN) into the Digital Link URL the chip emits, so a verifier that holds the chip's keys can prove the chip is genuine and the URL was not copied. The GS1 Web Vocabulary and EPCIS have no terms for that layer: the GS1 General Specifications call the medium a "data carrier" and stop there. This OpenEPCIS extension adds the missing metadata so that carrier binding, authentication keys and scan verdicts live on ordinary EPCIS events instead of in a database beside them.

The lifecycle is four EPCIS events. The brand owner reserves serials (ObjectEvent ADD, bizStep reserving) and publishes the per-serial SDM keys, sealed, together with the authentication profile that describes how the chip writes its URL. The labeller binds the chip UID to the serial (TransactionEvent, bizStep encoding). Commissioning is unchanged. Every authenticated scan becomes an ObjectEvent OBSERVE with bizStep inspecting that carries the read counter and the verdict: the CBV disposition conformant / non_conformant says pass or fail, carrier:authStatus says why (verified, replay, uid_mismatch, mac_invalid, picc_invalid, unknown_carrier). A verifier with EPCIS query access needs nothing else: the youngest key record, the youngest UID binding and the last read counter of the item.

Key fields are never stored in the clear. They are AES-256-GCM sealed under a wrapping key the event names in carrier:keyRef, with the canonical identifier as associated data, so a ciphertext copied onto another serial's event does not decrypt. The access-level sidecar classes the key fields AuthorizedOnly, binding and profile Restricted, and the verdict Public. Later business events (accepting, receiving, repairing, shipping) can cite the verified inspecting event through carrier:tapId and carrier:boundAt: proof that the party capturing the event physically held the item when it acted. A resolver maps the verdict and the item's last disposition onto GS1 Digital Link link contexts, so a verified owner, a replayed URL and a recalled item each land on the right page.

Upstream alignment

How this module's terms align to or build on external and upstream vocabularies. Open a vocabulary to see the exact term-by-term relationships.

DescriptionSubclass OfVocabularies
AuthProfile
Carrier Authentication Profile
How a carrier presents itself at a scan: the scheme, the URL parameters it mirrors into, and how its keys derive. Mirrors the tag's file settings so a verifier reads the URL the way the tag writes it.-—
Verification
Carrier Verification
The answer of a verifier to one scan: identifier, status, read counter and key reference.-—

Usage examples

Reserving event with sealed keys

The brand owner reserves a serial and publishes its SDM keys sealed under wrapping key k1, plus the authentication profile. ObjectEvent ADD, bizStep reserving, disposition inactive.

{
  "@context": [
    "https://ref.gs1.org/standards/epcis/epcis-context.jsonld",
    "https://ref.openepcis.org/extensions/common/core/dpp-core-context.jsonld",
    "https://ref.openepcis.org/extensions/common/carrier/carrier-context.jsonld"
  ],
  "type": "ObjectEvent",
  "eventTime": "2026-10-23T09:00:00.000Z",
  "eventTimeZoneOffset": "+02:00",
  "action": "ADD",
  "bizStep": "reserving",
  "disposition": "inactive",
  "readPoint": { "id": "https://id.gs1.org/414/9521234000006" },
  "epcList": ["https://id.gs1.org/01/09521234000013/21/A1"],
  "sourceList": [{ "type": "owning_party", "source": "https://id.gs1.org/417/9521234000006" }],
  "destinationList": [{ "type": "possessing_party", "destination": "https://id.gs1.org/417/9521234000020" }],
  "carrier:keyRef": "demo/lot-2026-10/k1",
  "carrier:authProfile": {
    "carrier:scheme": "ntag424-sdm",
    "carrier:piccParam": "picc",
    "carrier:macParam": "cmac",
    "carrier:piccEncrypted": true,
    "carrier:macInput": "none",
    "carrier:diversification": "sgtin",
    "carrier:urlTemplate": "https://id.epc.is/01/{gtin}/21/{serial}?picc={picc}&cmac={cmac}"
  },
  "carrier:sdmMetaReadKey": "enc:a256gcm:k1:5R1xq0mbTO8r6kHbxwYzqV4V4L3G0lVtDb5s0y1k2xJ7fXl3Q2cY9Mm1aN5OqJ8",
  "carrier:sdmFileReadKey": "enc:a256gcm:k1:Jg0rN3pQ2VzXcY9r7aK1mO5sLw8tF2hD4bE6nG7iH9jK0lM1nO2pQ3rS4tU5vW6"
}

Encoding event binding the chip

The labeller writes the tag and binds the chip UID to the serial. TransactionEvent, bizStep encoding (CBV), against the labelling purchase order.

{
  "@context": [
    "https://ref.gs1.org/standards/epcis/epcis-context.jsonld",
    "https://ref.openepcis.org/extensions/common/carrier/carrier-context.jsonld"
  ],
  "type": "TransactionEvent",
  "eventTime": "2026-10-24T10:30:00.000Z",
  "eventTimeZoneOffset": "+02:00",
  "action": "ADD",
  "bizStep": "encoding",
  "disposition": "inactive",
  "readPoint": { "id": "https://id.gs1.org/414/9521234000020/254/ENCODER-1" },
  "bizLocation": { "id": "https://id.gs1.org/414/9521234000020" },
  "bizTransactionList": [
    { "type": "po", "bizTransaction": "urn:epcglobal:cbv:bt:9521234000006:LABEL-2026-1042" }
  ],
  "epcList": ["https://id.gs1.org/01/09521234000013/21/A1"],
  "carrier:uid": "04DE5F1EACC040",
  "carrier:carrierType": "NTAG424DNA"
}

Inspecting OBSERVE event: one authenticated scan

The verifier records a tap. ObjectEvent OBSERVE, bizStep inspecting; disposition conformant carries pass/fail, carrier:authStatus the reason, carrier:readCounter the replay-detection state. This is the event every resolver reads.

{
  "@context": [
    "https://ref.gs1.org/standards/epcis/epcis-context.jsonld",
    "https://ref.openepcis.org/extensions/common/core/dpp-core-context.jsonld",
    "https://ref.openepcis.org/extensions/common/carrier/carrier-context.jsonld"
  ],
  "type": "ObjectEvent",
  "eventID": "urn:uuid:3f0d5e4a-9c1b-5d2e-8f4a-6b3c5a6c0b2e",
  "eventTime": "2026-11-02T15:12:41.000Z",
  "eventTimeZoneOffset": "+00:00",
  "action": "OBSERVE",
  "bizStep": "inspecting",
  "disposition": "conformant",
  "readPoint": { "id": "https://id.gs1.org/414/9521234000006/254/RESOLVER" },
  "epcList": ["https://id.gs1.org/01/09521234000013/21/A1"],
  "carrier:authStatus": "verified",
  "carrier:readCounter": 61,
  "carrier:keyRef": "demo/lot-2026-10/k1"
}

Business event resting on a verified tap

The new owner accepts the item. The accepting OBSERVE event cites the inspecting event through carrier:tapId, so the ownership change is backed by physical possession at that moment.

{
  "@context": [
    "https://ref.gs1.org/standards/epcis/epcis-context.jsonld",
    "https://ref.openepcis.org/extensions/common/carrier/carrier-context.jsonld"
  ],
  "type": "ObjectEvent",
  "eventTime": "2026-11-02T15:14:02.000Z",
  "eventTimeZoneOffset": "+00:00",
  "action": "OBSERVE",
  "bizStep": "accepting",
  "disposition": "active",
  "readPoint": { "id": "https://id.gs1.org/414/9521234000006/254/RESOLVER" },
  "epcList": ["https://id.gs1.org/01/09521234000013/21/A1"],
  "destinationList": [{ "type": "owning_party", "destination": "https://id.gs1.org/417/9521234000044" }],
  "carrier:tapId": "urn:uuid:3f0d5e4a-9c1b-5d2e-8f4a-6b3c5a6c0b2e",
  "carrier:boundAt": "2026-11-02T15:13:10Z"
}

Example files

Complete JSON-LD documents shipped with the vocabulary. Click a file to view the raw payload.

Quick start

Add the carrier context on top of the EPCIS and dpp-core contexts and declare the extension in the GS1-Extensions header of each capture (carrier=https://ref.openepcis.org/extensions/common/carrier/). Start with the inspecting event: it is the one every verifier writes and every resolver reads, and it needs three fields. Keys belong in reserving events, sealed under your wrapping key, never in the clear; the chip binding belongs in the labeller's encoding event. Re-keying is a new reserving-style event; a verifier always takes the youngest key record and the youngest UID binding. The reference implementation openepcis-carrier-auth (Java core, Quarkus extension, verifier service, provisioning CLI) produces exactly these events.

Context URL

https://ref.openepcis.org/extensions/common/carrier/carrier-context.jsonld
{
  "@context": [
    "https://ref.gs1.org/standards/epcis/epcis-context.jsonld",
    "https://ref.openepcis.org/extensions/common/carrier/carrier-context.jsonld"
  ],
  "type": "ObjectEvent",
  "action": "OBSERVE",
  "bizStep": "inspecting",
  "disposition": "conformant",
  "epcList": ["https://id.gs1.org/01/09521234000013/21/A1"],
  "carrier:authStatus": "verified",
  "carrier:readCounter": 61,
  "carrier:keyRef": "demo/lot-2026-10/k1"
}

Regulatory context

  • NXP AN12196 — NTAG 424 DNA and NTAG 424 DNA TagTamper features and hints: Secure Dynamic Messaging, PICC data encryption, SDM MAC and read counter
  • NXP AN10922 — Symmetric key diversification: per-carrier keys derived from a master key, by identifier (sgtin) or by chip UID
  • GS1 General Specifications, section 2 — Data carriers: the physical media (barcodes, RFID, NFC) that carry GS1 identifiers; the vocabulary names the medium, not its authentication
  • EPCIS 2.0, section 12.3 — User and vendor extension mechanism: carrier terms ride on standard events, declared through the GS1-Extensions capture header
  • GS1 Digital Link — The URL the chip emits and the link contexts (auth:verified, auth:replay, state:<disposition>) a resolver answers with