### Build the NTAG424 Java Library Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Use Maven to clean and install the library, producing a JAR file in the target directory. ```bash mvn clean install ``` -------------------------------- ### Get and Change File Settings - NTAG424 Source: https://context7.com/johnnyb/ntag424-java/llms.txt Retrieves and modifies file settings, including access permissions and SDM configuration for NTAG424 files. Requires prior authentication. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.GetFileSettings; import net.bplearning.ntag424.command.ChangeFileSettings; import net.bplearning.ntag424.command.FileSettings; import net.bplearning.ntag424.CommunicationMode; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.constants.Permissions; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // Get current settings for NDEF file FileSettings settings = GetFileSettings.run(communicator, Ntag424.NDEF_FILE_NUMBER); System.out.println("Communication mode: " + settings.commMode); System.out.println("File size: " + settings.fileSize); System.out.println("Read permission: " + settings.readPerm); System.out.println("Write permission: " + settings.writePerm); System.out.println("SDM enabled: " + settings.sdmSettings.sdmEnabled); // Modify settings settings.commMode = CommunicationMode.PLAIN; settings.readPerm = Permissions.ACCESS_EVERYONE; // 0x0E - public read settings.writePerm = Permissions.ACCESS_KEY0; // Require key 0 for write settings.readWritePerm = Permissions.ACCESS_KEY0; settings.changePerm = Permissions.ACCESS_KEY0; // Apply changes ChangeFileSettings.run(communicator, Ntag424.NDEF_FILE_NUMBER, settings); ``` -------------------------------- ### Authenticate with AES Encryption Mode Source: https://context7.com/johnnyb/ntag424-java/llms.txt Establishes a secure AES-encrypted session using `authenticateEV2`. Requires prior communication setup and authentication with a valid key. Session keys are generated for subsequent encrypted commands. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; import net.bplearning.ntag424.constants.Ntag424; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); // Authenticate with key 0 using factory key (all zeros) int keyNumber = 0; byte[] key = Ntag424.FACTORY_KEY; // new byte[16] - factory default boolean success = AESEncryptionMode.authenticateEV2(communicator, keyNumber, key); if (success) { // Session established - encrypted commands now available System.out.println("Authentication successful"); System.out.println("Active key: " + communicator.getActiveKeyNumber()); System.out.println("Command counter: " + communicator.getCommandCounter()); } else { System.out.println("Authentication failed - check key"); } ``` -------------------------------- ### Authenticate with LRP Encryption Mode Source: https://context7.com/johnnyb/ntag424-java/llms.txt Establishes a secure session using LRP encryption with `authenticateLRP`. LRP mode must be permanently enabled on the tag first. This method requires prior communication setup and authentication. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.encryptionmode.LRPEncryptionMode; import net.bplearning.ntag424.command.SetCapabilities; import net.bplearning.ntag424.constants.Ntag424; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); // IMPORTANT: First enable LRP mode permanently (one-time, irreversible) // Must be authenticated with AES first to set capabilities // AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // SetCapabilities.run(communicator, true); // WARNING: Permanent! // Authenticate using LRP mode int keyNumber = 0; byte[] key = Ntag424.FACTORY_KEY; boolean success = LRPEncryptionMode.authenticateLRP(communicator, keyNumber, key); if (success) { System.out.println("LRP authentication successful"); System.out.println("Using LRP: " + communicator.isUsingLRP()); // true } ``` -------------------------------- ### DnaCommunicator - Core Communication Source: https://context7.com/johnnyb/ntag424-java/llms.txt The DnaCommunicator class manages the lifecycle of the NFC session, including transceiver setup, logging, and session state tracking. ```APIDOC ## DnaCommunicator ### Description Central handler for NTAG 424 DNA chip interactions. Manages command packaging and session state. ### Methods - **setTransceiver(Transceiver)**: Sets the interface to the NFC hardware. - **setLogger(Logger)**: Configures a logger for debugging. - **beginCommunication()**: Initializes the session with the tag. - **isLoggedIn()**: Returns boolean status of authentication. - **isUsingLRP()**: Returns true if LRP mode is active. - **getCommandCounter()**: Returns the current command counter value. ``` -------------------------------- ### Key Diversification with KeyInfo Source: https://context7.com/johnnyb/ntag424-java/llms.txt Demonstrates setting up KeyInfo for key diversification using a master key and application identifier. It shows how to generate a card-specific key from a UID and synchronize it on the tag. Also includes validation of SDM MAC with the diversified key. ```java import net.bplearning.ntag424.card.KeyInfo; import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.GetCardUid; import net.bplearning.ntag424.command.ChangeKey; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; import net.bplearning.ntag424.util.ByteUtil; // Setup key info with diversification KeyInfo keyInfo = new KeyInfo(); keyInfo.key = new byte[] { // Master key (keep secret!) 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; keyInfo.diversifyKeys = true; keyInfo.systemIdentifier = "myapp".getBytes(); // Application identifier keyInfo.version = 1; // Generate card-specific key from UID byte[] cardUid = new byte[] { 0x04, (byte)0xA1, (byte)0xB2, (byte)0xC3, (byte)0xD4, (byte)0xE5, (byte)0xF6 }; byte[] cardSpecificKey = keyInfo.generateKeyForCardUid(cardUid); System.out.println("Diversified key: " + ByteUtil.byteToHex(cardSpecificKey)); // Synchronize keys on a tag (updates from old key to new key) DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // This checks if key needs updating and applies changes boolean synced = keyInfo.synchronizeKey(cardUid, communicator, 3); // Sync key 3 // Validate SDM MAC with diversified key String uidStr = "04A1B2C3D4E5F6"; String ctrStr = "000001"; String macStr = "AABBCCDD11223344"; PiccData result = keyInfo.decodeAndVerifyMac(uidStr, ctrStr, macStr, false); if (result != null) { System.out.println("Valid SDM message from card: " + result.getUidString()); } ``` -------------------------------- ### Configure SDM and NDEF Template in Java Source: https://context7.com/johnnyb/ntag424-java/llms.txt Configures SDM settings and writes an NDEF template to the NTAG424 chip. Requires an active DnaCommunicator session and appropriate file permissions. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.sdm.SDMSettings; import net.bplearning.ntag424.sdm.NdefTemplateMaster; import net.bplearning.ntag424.command.WriteData; import net.bplearning.ntag424.command.GetFileSettings; import net.bplearning.ntag424.command.ChangeFileSettings; import net.bplearning.ntag424.command.FileSettings; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.constants.Permissions; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // Configure SDM settings SDMSettings sdmSettings = new SDMSettings(); sdmSettings.sdmMetaReadPerm = Permissions.ACCESS_EVERYONE; // Plaintext PICC data sdmSettings.sdmFileReadPerm = Permissions.ACCESS_KEY2; // Key for MAC generation sdmSettings.sdmReadCounterRetrievalPerm = Permissions.ACCESS_NONE; sdmSettings.sdmOptionUid = true; sdmSettings.sdmOptionReadCounter = true; sdmSettings.sdmOptionUseAscii = true; // Create NDEF template // Placeholders: {UID}, {COUNTER}, {MAC}, {PICC}, {FILE}, ^ (MAC input start) NdefTemplateMaster master = new NdefTemplateMaster(); master.usesLRP = false; String urlTemplate = "https://example.com/verify?uid={UID}&ctr={COUNTER}&mac={MAC}"; byte[] ndefRecord = master.generateNdefTemplateFromUrlString(urlTemplate, sdmSettings); // Write NDEF record to file WriteData.run(communicator, Ntag424.NDEF_FILE_NUMBER, ndefRecord); // Apply SDM settings to file FileSettings ndefFileSettings = GetFileSettings.run(communicator, Ntag424.NDEF_FILE_NUMBER); defFileSettings.readPerm = Permissions.ACCESS_EVERYONE; defFileSettings.writePerm = Permissions.ACCESS_KEY0; defFileSettings.sdmSettings = sdmSettings; ChangeFileSettings.run(communicator, Ntag424.NDEF_FILE_NUMBER, ndefFileSettings); ``` -------------------------------- ### Generate SDM Settings and NDEF Record Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Creates SDM settings, defines file permissions, and generates an NDEF record from a URL template. Ensure LRP usage is correctly set on the NdefTemplateMaster if applicable. ```java // Generate a new SDMSettings object and set the access permissions SDMSettings sdmSettings = new SDMSettings(); sdmSettings.sdmMetaReadPerm = Constants.ACCESS_EVERYONE; // Set to a key to get encrypted PICC data sdmSettings.sdmFileReadPerm = Constants.ACCESS_KEY2; // Used to create the MAC and Encrypt FileData sdmSettings.sdmReadCounterRetrievalPerm = Constants.ACCESS_NONE; // Not sure what this is for // Create the NDEF record and make appropriate updates to SDMSettings byte[] ndefRecord = master.generateNdefTemplateFromUrlString("https://www.example.com/{UID}{COUNTER}/{MAC}", sdmSettings); ``` -------------------------------- ### Generate Random Key Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Generates a 16-byte random key using system entropy. ```bash head -c 16 /dev/random|xxd -p ``` -------------------------------- ### ByteUtil Integer/Byte Conversion (LSB-first) Source: https://context7.com/johnnyb/ntag424-java/llms.txt Converts between integers and byte arrays using Least Significant Byte (LSB) first order. Also extracts individual bytes from an integer. ```java import net.bplearning.ntag424.util.ByteUtil; // Integer/byte conversion (LSB-first) int value = ByteUtil.lsbBytesToInt(new byte[] {0x01, 0x00, 0x00}); // 1 byte lsb = ByteUtil.getByteLSB(256, 0); // 0x00 (LSB) byte msb = ByteUtil.getByteLSB(256, 1); // 0x01 (next byte) ``` -------------------------------- ### Update Tag File Settings for SDM Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Retrieves existing file settings for the NDEF file, modifies them to include the new SDM settings, and applies the changes to the tag. ```java // Get the existing file settings: FileSettings ndeffs = GetFileSettings.run(communicator, Constants.NDEF_FILE_NUMBER); // Make any modifications you would like to those settings/permissions // ... // Set the SDMSettings to the newly-created sdmSettings object ndeffs.sdmSettings = sdmSettings; // Make changes to the file ChangeFileSettings.run(communicator, Constants.NDEF_FILE_NUMBER, ndeffs); ``` -------------------------------- ### Initialize PiccData for Unencrypted PICC Data Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Constructs a PiccData object for validating unencrypted PICC data. Provide the UID and read counter if they are mirrored; otherwise, use null or 0. ```java PiccData picc = new PiccData(uid, readCounter, usesLrp); ``` -------------------------------- ### Validate SDM Data Server-Side in Java Source: https://context7.com/johnnyb/ntag424-java/llms.txt Validates incoming SDM parameters using the PiccData class. Supports both all-in-one verification and manual MAC comparison. ```java import net.bplearning.ntag424.sdm.PiccData; import net.bplearning.ntag424.util.ByteUtil; // Validate SDM data from URL parameters // Example URL: https://example.com/verify?uid=04A1B2C3D4E5F6&ctr=000001&mac=AABBCCDD11223344 String uidString = "04A1B2C3D4E5F6"; String counterString = "000001"; String macString = "AABBCCDD11223344"; byte[] macKey = new byte[] { /* your MAC file key */ }; boolean usesLrp = false; // Method 1: All-in-one validation (returns null if MAC invalid) PiccData piccData = PiccData.decodeAndVerifyMac( uidString, counterString, macString, macKey, usesLrp ); if (piccData != null) { System.out.println("MAC valid!"); System.out.println("UID: " + piccData.getUidString()); System.out.println("Read counter: " + piccData.getReadCounter()); } else { System.out.println("Invalid MAC - possible tampering"); } // Method 2: Manual validation with more control PiccData picc = new PiccData( ByteUtil.hexToByte(uidString), (int) ByteUtil.msbBytesToLong(ByteUtil.hexToByte(counterString)), usesLrp ); picc.setMacFileKey(macKey); // Generate expected MAC and compare byte[] expectedMac = picc.performShortCMAC(null); // null for PICC-only MAC byte[] actualMac = ByteUtil.hexToByte(macString); if (ByteUtil.arraysEqual(expectedMac, actualMac)) { System.out.println("Validation successful"); } // Decrypt encrypted file data if present byte[] encryptedFileData = ByteUtil.hexToByte("..."); byte[] decryptedData = picc.decryptFileData(encryptedFileData); ``` -------------------------------- ### Configure Tag for LRP Encryption Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Use this command to set the NTAG424 tag to LRP encryption mode. This is a one-way operation; tags cannot be switched back to AES mode after configuration. ```java import net.bplearning.ntag424.command.SetCapabilities; SetCapabilities.run(communicator, true); ``` -------------------------------- ### Android NFC Tag Interaction with NTAG424 Library Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Demonstrates how to use the NTAG424 library within an Android project after discovering an NFC tag. It includes connecting to the tag, setting up the communicator, authenticating, and retrieving the Card UID. ```java import android.nfc.Tag; import android.nfc.tech.IsoDep; import net.bplearning.ntag424.Constants; import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.GetCardUid; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; ... Tag tag = tagIntent.getParcelableExtra(NfcAdapter.EXTRA_TAG); IsoDep iso = IsoDep.get(tag); new Thread(() -> { try { iso.connect(); // Connect the library to the Android tag transceiver DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); // This is required to use the functionality of the chip. It's a weird NFC thing. IsoSelectFile.run(communicator, IsoSelectFile.SELECT_MODE_BY_FILE_IDENTIFIER, Constants.DF_FILE_ID); // Try to authenticate with the factory key and start an encrypted session if(AESEncryptionMode.authenticateEV2(communicator, 0, Constants.FACTORY_KEY)) { // Run an encrypted command to get the Card UID byte[] cardUid = GetCardUid.run(communicator); } else { // Failed to authenticate } } catch(IOException e) { // Always expect IOExceptions - they can happen even from someone not holding the // tag in place long enough. } }).start(); ``` -------------------------------- ### Validate SDM MAC and Decrypt File Data Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Sets the MAC file key, performs MAC validation on the provided message (or PICC-only data if the message is empty), and decrypts file data if present. ```java picc.setMacFileKey(macFileKey); picc.performShortMac(new byte[0]); // MAC on PICC-only data picc.decryptFileData(filedata); ``` -------------------------------- ### Write File Data with NTAG424 Java Source: https://context7.com/johnnyb/ntag424-java/llms.txt Writes data to a file on the chip. The communication mode is automatically determined from the file's settings, or can be specified explicitly. Authentication is required. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.WriteData; import net.bplearning.ntag424.CommunicationMode; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // Write to the proprietary data file (file number 3) int fileNum = Ntag424.DATA_FILE_NUMBER; // 0x03 byte[] dataToWrite = "Hello NFC World!".getBytes(); // Write at the beginning of the file WriteData.run(communicator, fileNum, dataToWrite); // Write at specific offset int offset = 64; WriteData.run(communicator, fileNum, dataToWrite, offset); // Write with explicit communication mode WriteData.run(communicator, CommunicationMode.FULL, fileNum, dataToWrite, 0); ``` -------------------------------- ### Generate Diversified Card Key Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Uses the KeyInfo class to derive a unique key for a specific tag UID based on a master key and system identifier. ```java byte[] masterKey = new byte[]{ /* Your master key here */ }; KeyInfo keyInfo = new KeyInfo(); keyInfo.key = masterKey; keyInfo.systemIdentifier = new byte[] {0x66, 0x6f, 0x6f}; keyInfo.diversifyKeys = true; byte[] cardKey = keyInfo.generateKeyForCardUid(uidBytes); ``` -------------------------------- ### Initialize DnaCommunicator with Android NFC Tag Source: https://context7.com/johnnyb/ntag424-java/llms.txt Initializes the `DnaCommunicator` with an Android NFC tag and sets up the transceiver for communication. Begin communication session before any operations. ```java import android.nfc.Tag; import android.nfc.tech.IsoDep; import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.command.IsoSelectFile; // Initialize communicator with Android NFC tag Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); IsoDep iso = IsoDep.get(tag); iso.connect(); DnaCommunicator communicator = new DnaCommunicator(); // Set transceiver to bridge to Android NFC communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); // Optional: Enable logging for debugging communicator.setLogger((info) -> Log.d("NFC", info)); // Begin communication session (required before any operations) communicator.beginCommunication(); // Check session status boolean loggedIn = communicator.isLoggedIn(); // false until authenticated boolean usingLrp = communicator.isUsingLRP(); // false for AES mode int cmdCounter = communicator.getCommandCounter(); ``` -------------------------------- ### Read File Data with NTAG424 Java Source: https://context7.com/johnnyb/ntag424-java/llms.txt Reads data from one of the three files on the NTAG 424 DNA chip. Communication mode is automatically determined from file settings. Authentication is required. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.ReadData; import net.bplearning.ntag424.CommunicationMode; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // Read from NDEF file (file number 2) int fileNum = Ntag424.NDEF_FILE_NUMBER; // 0x02 int offset = 0; int length = 256; // Read up to 256 bytes // Auto-detect communication mode from file settings byte[] data = ReadData.run(communicator, fileNum, offset, length); System.out.println("Read " + data.length + " bytes"); // Or specify communication mode explicitly byte[] dataPlain = ReadData.run(communicator, CommunicationMode.PLAIN, fileNum, offset, length); byte[] dataMac = ReadData.run(communicator, CommunicationMode.MAC, fileNum, offset, length); byte[] dataFull = ReadData.run(communicator, CommunicationMode.FULL, fileNum, offset, length); ``` -------------------------------- ### ByteUtil Combine Byte Arrays Source: https://context7.com/johnnyb/ntag424-java/llms.txt Combines multiple byte arrays into a single new byte array. ```java import net.bplearning.ntag424.util.ByteUtil; // Combine multiple arrays byte[] combined = ByteUtil.combineByteArrays( new byte[] {0x01, 0x02}, new byte[] {0x03, 0x04}, new byte[] {0x05} ); // {0x01, 0x02, 0x03, 0x04, 0x05} ``` -------------------------------- ### ByteUtil Random Data Generation Source: https://context7.com/johnnyb/ntag424-java/llms.txt Generates a byte array of a specified length filled with random data. ```java import net.bplearning.ntag424.util.ByteUtil; // Random data generation byte[] randomBytes = ByteUtil.randomByteArray(16); ``` -------------------------------- ### LRPEncryptionMode.authenticateLRP Source: https://context7.com/johnnyb/ntag424-java/llms.txt Establishes a secure session using the Leakage-Resistant Primitive (LRP) encryption mode. ```APIDOC ## LRPEncryptionMode.authenticateLRP ### Description Authenticates the session using LRP mode. Note: LRP mode must be permanently enabled on the tag via SetCapabilities before use. ### Parameters - **communicator** (DnaCommunicator) - Required - The active communication handler. - **keyNumber** (int) - Required - The key index to use for authentication. - **key** (byte[]) - Required - The 16-byte LRP key. ### Response - **success** (boolean) - Returns true if authentication is successful. ``` -------------------------------- ### ByteUtil Array Operations Source: https://context7.com/johnnyb/ntag424-java/llms.txt Provides functions for manipulating byte arrays, including creating subarrays and comparing arrays for equality. ```java import net.bplearning.ntag424.util.ByteUtil; // Array operations byte[] data = new byte[] { 0x04, (byte)0xA1, (byte)0xB2, (byte)0xC3 }; byte[] subArray = ByteUtil.subArrayOf(data, 1, 2); // {0xA1, 0xB2} boolean equal = ByteUtil.arraysEqual(data, fromHex); // true ``` -------------------------------- ### WriteData Source: https://context7.com/johnnyb/ntag424-java/llms.txt Writes data to a file on the chip. The communication mode is automatically determined from the file's settings, or can be specified explicitly. ```APIDOC ## WriteData ### Description Writes data to a file on the chip. The communication mode is automatically determined from the file's settings, or can be specified explicitly. ### Parameters - **fileNum** (int) - Required - The file number to write to. - **data** (byte[]) - Required - The data to write. - **offset** (int) - Optional - The starting offset in the file. - **mode** (CommunicationMode) - Optional - Explicit communication mode (PLAIN, MAC, FULL). ``` -------------------------------- ### Change Authentication Keys - NTAG424 Source: https://context7.com/johnnyb/ntag424-java/llms.txt Updates application keys on the NTAG424 chip. Key 0 (master key) can be changed without the old key, while other keys require both old and new keys. Requires authentication with key 0. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.ChangeKey; import net.bplearning.ntag424.command.GetKeyVersion; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); // Must authenticate with key 0 to change any key AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // Check current key version int currentVersion = GetKeyVersion.run(communicator, 0); System.out.println("Current key 0 version: " + currentVersion); // Change key 0 (master key) - no old key needed byte[] newKey = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }; int newKeyVersion = 1; ChangeKey.run(communicator, 0, null, newKey, newKeyVersion); // Session will be re-authenticated automatically // Change key 3 - requires both old and new key byte[] oldKey3 = Ntag424.FACTORY_KEY; byte[] newKey3 = new byte[] { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 }; ChangeKey.run(communicator, 3, oldKey3, newKey3, 1); ``` -------------------------------- ### ByteUtil Hex Conversion Source: https://context7.com/johnnyb/ntag424-java/llms.txt Converts byte arrays to hexadecimal strings and vice versa. Useful for data representation and debugging. ```java import net.bplearning.ntag424.util.ByteUtil; // Hex conversion byte[] data = new byte[] { 0x04, (byte)0xA1, (byte)0xB2, (byte)0xC3 }; String hexString = ByteUtil.byteToHex(data); // "04A1B2C3" byte[] fromHex = ByteUtil.hexToByte("04A1B2C3"); // back to bytes ``` -------------------------------- ### AESEncryptionMode.authenticateEV2 Source: https://context7.com/johnnyb/ntag424-java/llms.txt Establishes a secure AES-encrypted session with the NTAG 424 DNA chip using mutual authentication. ```APIDOC ## AESEncryptionMode.authenticateEV2 ### Description Performs mutual authentication and generates session keys for encrypted commands using AES. ### Parameters - **communicator** (DnaCommunicator) - Required - The active communication handler. - **keyNumber** (int) - Required - The key index to use for authentication. - **key** (byte[]) - Required - The 16-byte AES key. ### Response - **success** (boolean) - Returns true if authentication is successful. ``` -------------------------------- ### Write SDM NDEF Data to Tag Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Writes the generated NDEF record containing SDM data to the specified NDEF file on the tag. ```java // Write the data to the NDEF file WriteData.run(communicator, Constants.NDEF_FILE_NUMBER, ndefRecord); ``` -------------------------------- ### ByteUtil Byte Rotation Source: https://context7.com/johnnyb/ntag424-java/llms.txt Performs left or right rotation on a byte array by a specified number of positions. ```java import net.bplearning.ntag424.util.ByteUtil; // Byte rotation byte[] original = new byte[] {0x01, 0x02, 0x03, 0x04}; byte[] rotLeft = ByteUtil.rotateLeft(original, 1); // {0x02, 0x03, 0x04, 0x01} byte[] rotRight = ByteUtil.rotateRight(original, 1); // {0x04, 0x01, 0x02, 0x03} ``` -------------------------------- ### Complete Android NFC Integration with NTAG 424 DNA Source: https://context7.com/johnnyb/ntag424-java/llms.txt This code demonstrates a full Android NFC application workflow. It includes tag discovery, authentication using AES, and SDM configuration for secure URLs. Ensure NFC is enabled and the app has necessary permissions. ```java import android.app.PendingIntent; import android.content.Intent; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.*; import net.bplearning.ntag424.constants.Ntag424; import net.bplearning.ntag424.constants.Permissions; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; import net.bplearning.ntag424.sdm.NdefTemplateMaster; import net.bplearning.ntag424.sdm.SDMSettings; import net.bplearning.ntag424.util.ByteUtil; public class NfcActivity extends AppCompatActivity { private NfcAdapter nfcAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); nfcAdapter = NfcAdapter.getDefaultAdapter(this); } @Override protected void onResume() { super.onResume(); Intent intent = new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE); nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null); } @Override protected void onPause() { super.onPause(); nfcAdapter.disableForegroundDispatch(this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if (tag != null) processTag(tag); } private void processTag(Tag tag) { new Thread(() -> { try { IsoDep iso = IsoDep.get(tag); iso.connect(); // Initialize communicator DnaCommunicator comm = new DnaCommunicator(); comm.setTransceiver(iso::transceive); comm.beginCommunication(); // Authenticate if (!AESEncryptionMode.authenticateEV2(comm, 0, Ntag424.FACTORY_KEY)) { showToast("Authentication failed"); return; } // Get card info byte[] uid = GetCardUid.run(comm); int keyVersion = GetKeyVersion.run(comm, 0); showToast("UID: " + ByteUtil.byteToHex(uid)); // Configure SDM for secure URLs SDMSettings sdm = new SDMSettings(); sdm.sdmMetaReadPerm = Permissions.ACCESS_EVERYONE; sdm.sdmFileReadPerm = Permissions.ACCESS_KEY2; sdm.sdmOptionUid = true; sdm.sdmOptionReadCounter = true; NdefTemplateMaster master = new NdefTemplateMaster(); byte[] ndefData = master.generateNdefTemplateFromUrlString( "https://verify.example.com/?u={UID}&c={COUNTER}&m={MAC}", sdm ); WriteData.run(comm, Ntag424.NDEF_FILE_NUMBER, ndefData); FileSettings fs = GetFileSettings.run(comm, Ntag424.NDEF_FILE_NUMBER); fs.sdmSettings = sdm; fs.readPerm = Permissions.ACCESS_EVERYONE; ChangeFileSettings.run(comm, Ntag424.NDEF_FILE_NUMBER, fs); showToast("Tag configured successfully!"); iso.close(); } catch (Exception e) { showToast("Error: " + e.getMessage()); } }).start(); } private void showToast(String msg) { runOnUiThread(() -> android.widget.Toast.makeText(this, msg, android.widget.Toast.LENGTH_SHORT).show()); } } ``` -------------------------------- ### ByteUtil XOR Operation Source: https://context7.com/johnnyb/ntag424-java/llms.txt Performs a bitwise XOR operation between two byte arrays of the same length. ```java import net.bplearning.ntag424.util.ByteUtil; // XOR operations byte[] a = new byte[] {0x0F, 0xF0}; byte[] b = new byte[] {0x55, 0xAA}; byte[] xored = ByteUtil.xor(a, b); // {0x5A, 0x5A} ``` -------------------------------- ### Decode PiccData from Encrypted Bytes Source: https://github.com/johnnyb/ntag424-java/blob/main/README.md Decodes PiccData from encrypted byte data. Requires the encryption key and a boolean indicating if LRP is used. The key may differ from the MAC/file decryption key. ```java PiccData picc = PiccData.decodeFromEncryptedBytes(encryptedBytes, key, usesLrp); ``` -------------------------------- ### ReadData Source: https://context7.com/johnnyb/ntag424-java/llms.txt Reads data from one of the three files on the NTAG 424 DNA chip (CC file, NDEF file, or proprietary data file). ```APIDOC ## ReadData ### Description Reads data from one of the three files on the NTAG 424 DNA chip. Communication mode is automatically determined from file settings or can be specified. ### Parameters - **fileNum** (int) - Required - The file number to read from (e.g., NDEF_FILE_NUMBER). - **offset** (int) - Required - The starting offset in the file. - **length** (int) - Required - The number of bytes to read. - **mode** (CommunicationMode) - Optional - Explicit communication mode (PLAIN, MAC, FULL). ### Response - **data** (byte[]) - The data read from the specified file. ``` -------------------------------- ### Retrieve Card UID with NTAG424 Java Source: https://context7.com/johnnyb/ntag424-java/llms.txt Retrieves the unique 7-byte identifier of the NFC tag. Requires an authenticated session. The UID is transmitted encrypted. ```java import net.bplearning.ntag424.DnaCommunicator; import net.bplearning.ntag424.command.GetCardUid; import net.bplearning.ntag424.encryptionmode.AESEncryptionMode; import net.bplearning.ntag424.util.ByteUtil; import net.bplearning.ntag424.constants.Ntag424; DnaCommunicator communicator = new DnaCommunicator(); communicator.setTransceiver((bytesToSend) -> iso.transceive(bytesToSend)); communicator.beginCommunication(); // Must authenticate first AESEncryptionMode.authenticateEV2(communicator, 0, Ntag424.FACTORY_KEY); // Get the card UID (7 bytes) byte[] cardUid = GetCardUid.run(communicator); // Convert to hex string for display String uidString = ByteUtil.byteToHex(cardUid); System.out.println("Card UID: " + uidString); // e.g., "04A1B2C3D4E5F6" ``` -------------------------------- ### ByteUtil Nibble Operations Source: https://context7.com/johnnyb/ntag424-java/llms.txt Extracts the left or right nibble (4 bits) from a byte. ```java import net.bplearning.ntag424.util.ByteUtil; // Nibble operations int leftNibble = ByteUtil.leftNibble((byte)0xAB); // 0x0A (10) int rightNibble = ByteUtil.rightNibble((byte)0xAB); // 0x0B (11) ``` -------------------------------- ### GetCardUid Source: https://context7.com/johnnyb/ntag424-java/llms.txt Retrieves the unique 7-byte identifier of the NFC tag. Requires an authenticated session as the UID is transmitted encrypted. ```APIDOC ## GetCardUid ### Description Retrieves the unique 7-byte identifier of the NFC tag. This requires an authenticated session as the UID is transmitted encrypted. ### Request Example GetCardUid.run(communicator); ### Response - **cardUid** (byte[]) - The 7-byte unique identifier of the NFC tag. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.