Features Solutions Technology Tokenomics Docs About
Docs / NFC Integration / Encoding Guide

NFC Encoding Guide

Properly encoding NFC chips ensures secure, tamper-proof product authentication.

Prerequisites

Before you begin encoding NFC chips, ensure you have the following:

Note

For production encoding, we recommend using our certified encoding stations. Contact sales for enterprise solutions.

Encoding Flow

The TAG IT encoding process follows these steps to ensure secure chip initialization:

  1. Initialize Session - Authenticate with the TAG IT API and create an encoding session
  2. Read Chip UID - Capture the unique identifier from the blank NFC chip
  3. Generate Keys - Request cryptographic keys from the TAG IT key management system
  4. Write NDEF Records - Program the authentication URL and metadata
  5. Configure Security - Set up counters, signatures, and access controls
  6. Lock Configuration - Permanently lock security settings to prevent tampering
  7. Register on Blockchain - Create the on-chain product record
  8. Verify Encoding - Perform a test scan to confirm successful encoding
// Complete encoding flow example
import { TagIt } from '@tagit/sdk';

const tagit = new TagIt({
  apiKey: process.env.TAGIT_API_KEY,
  network: 'mainnet'
});

async function encodeNFCChip(chipUID, productData) {
  // Step 1: Create encoding session
  const session = await tagit.encoding.createSession({
    chipUID: chipUID,
    productData: productData
  });

  // Step 2: Generate cryptographic keys
  const keys = await tagit.encoding.generateKeys(session.id);

  // Step 3: Prepare NDEF payload
  const ndefPayload = await tagit.encoding.prepareNDEF({
    sessionId: session.id,
    authUrl: `https://verify.tagit.network/${session.tagId}`,
    metadata: productData
  });

  // Step 4: Write to chip (requires NFC hardware)
  const writeResult = await nfcWriter.write(ndefPayload);

  // Step 5: Configure security features
  await tagit.encoding.configureSecurity({
    sessionId: session.id,
    enableCounter: true,
    enableSignature: true,
    lockConfig: true
  });

  // Step 6: Register on blockchain
  const registration = await tagit.encoding.register(session.id);

  return {
    tagId: session.tagId,
    txHash: registration.txHash,
    verifyUrl: ndefPayload.authUrl
  };
}

Data Format

TAG IT uses NDEF (NFC Data Exchange Format) records to store authentication data on chips.

NDEF Record Structure

Each TAG IT chip contains the following NDEF records:

{
  "records": [
    {
      "type": "U",
      "id": "tagit-auth",
      "payload": "https://verify.tagit.network/t/ABC123XYZ"
    },
    {
      "type": "T",
      "id": "tagit-meta",
      "payload": {
        "v": "1.0",
        "sig": "base64_encoded_signature",
        "cnt": "rolling_counter_value"
      }
    }
  ]
}

URL Structure

The authentication URL follows this format:

https://verify.tagit.network/t/{TAG_ID}?s={SIGNATURE}&c={COUNTER}

Parameters:
- TAG_ID: Unique 12-character alphanumeric identifier
- SIGNATURE: CMAC signature (16 bytes, hex encoded)
- COUNTER: Rolling counter value (3 bytes, hex encoded)

Security Features

TAG IT NFC chips incorporate multiple security layers to prevent counterfeiting and tampering.

Cryptographic Signatures

Each scan generates a unique CMAC (Cipher-based Message Authentication Code) signature using AES-128:

// Signature verification on server
async function verifySignature(tagId, signature, counter) {
  const chip = await tagit.chips.get(tagId);

  // Reconstruct the message that was signed
  const message = Buffer.concat([
    Buffer.from(chip.uid, 'hex'),
    Buffer.from(counter, 'hex'),
    Buffer.from(tagId)
  ]);

  // Verify using the chip's secret key
  const isValid = await tagit.crypto.verifyCMAC({
    key: chip.authKey,
    message: message,
    signature: signature
  });

  return isValid;
}
Security Warning

Authentication keys are never exposed. All signature verification happens server-side through the TAG IT API.

Rolling Counters

A monotonically increasing counter prevents replay attacks:

// Counter validation logic
async function validateCounter(tagId, receivedCounter) {
  const chip = await tagit.chips.get(tagId);
  const counterValue = parseInt(receivedCounter, 16);

  // Counter must be greater than last seen
  if (counterValue <= chip.lastCounter) {
    throw new Error('Replay attack detected: counter too low');
  }

  // Counter shouldn't jump too far (indicates cloning attempt)
  if (counterValue > chip.lastCounter + 1000) {
    await tagit.alerts.create({
      type: 'COUNTER_ANOMALY',
      tagId: tagId,
      details: { expected: chip.lastCounter + 1, received: counterValue }
    });
  }

  // Update stored counter
  await tagit.chips.updateCounter(tagId, counterValue);
  return true;
}

Tamper Detection

TAG IT chips can detect physical tampering attempts:

Batch Encoding

For manufacturing environments, TAG IT supports high-volume batch encoding:

// Batch encoding for manufacturing
import { TagIt, BatchEncoder } from '@tagit/sdk';

const tagit = new TagIt({ apiKey: process.env.TAGIT_API_KEY });

async function batchEncode(products) {
  // Create batch session
  const batch = await tagit.encoding.createBatch({
    name: 'Production Run 2024-001',
    quantity: products.length,
    productTemplate: {
      brand: 'Premium Brand',
      category: 'Luxury Goods'
    }
  });

  const encoder = new BatchEncoder({
    tagit: tagit,
    batchId: batch.id,
    onProgress: (progress) => {
      console.log(`Encoded ${progress.completed}/${progress.total}`);
    },
    onError: (error, chip) => {
      console.error(`Failed to encode ${chip.uid}: ${error.message}`);
    }
  });

  // Process each chip
  for (const product of products) {
    await encoder.encodeNext({
      serialNumber: product.serialNumber,
      metadata: product.metadata
    });
  }

  // Finalize batch and get report
  const report = await encoder.finalize();

  console.log(`Batch complete: ${report.successful}/${report.total} chips encoded`);
  console.log(`Blockchain TX: ${report.registrationTxHash}`);

  return report;
}
Enterprise Feature

Batch encoding with parallel processing is available on Business and Enterprise plans. Contact sales for encoding station hardware.

Verifying Encoded Tags

After encoding, always verify that tags are properly programmed:

// Post-encoding verification
async function verifyEncodedTag(tagId) {
  const verification = await tagit.encoding.verify(tagId);

  const checks = {
    ndefValid: verification.ndef.valid,
    signatureValid: verification.security.signatureEnabled,
    counterValid: verification.security.counterEnabled,
    configLocked: verification.security.configurationLocked,
    blockchainRegistered: verification.blockchain.registered,
    urlAccessible: verification.connectivity.urlReachable
  };

  const allPassed = Object.values(checks).every(v => v === true);

  if (!allPassed) {
    console.error('Verification failed:', checks);
    throw new Error('Tag encoding verification failed');
  }

  console.log('Tag verified successfully:', {
    tagId: tagId,
    verifyUrl: verification.urls.verify,
    txHash: verification.blockchain.txHash
  });

  return verification;
}

Testing Checklist

Troubleshooting

Common issues and their solutions:

Encoding Fails

Verification Fails After Encoding

Counter Anomalies

Need Help?

For encoding support, contact our technical team at support@tagit.network or visit the Developer Forum.

Edit this page on GitHub
Type to search documentation...