From dc1883ce558919d271f875a60d2e43d3e984d68a Mon Sep 17 00:00:00 2001 From: Roope Hakulinen Date: Mon, 18 Jun 2018 09:05:03 +0100 Subject: [PATCH 1/5] Add locking of tags. --- CHANGELOG.md | 5 ++ README.md | 69 ++++++++++++++- package.json | 2 +- plugin.xml | 2 +- .../CordovaPluginMifareUltralight.java | 83 +++++++++++++++---- src/android/MifareUltralight.java | 54 ++++++++++++ www/cordova-plugin-mifare-ultralight.js | 50 +++++++++-- 7 files changed, 241 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 450e956..d2f8f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# [1.1.0](https://github.com/RoopeHakulinen/cordova-plugin-mifare-ultralight/blob/master/CHANGELOG.md#1.1.0) (2018-06-15) + +Add possibility to lock different kinds of tags with a PIN code. + # [1.0.3](https://github.com/RoopeHakulinen/cordova-plugin-mifare-ultralight/blob/master/CHANGELOG.md#1.0.3) (2018-04-12) diff --git a/README.md b/README.md index bae0545..3c827bb 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This plugins lets you interact with Mifare Ultralight NFC tags on Android devices. You can use it to - Detect Mifare Ultralight tag near-by the device. - Connect/disconnet with Mifare Ultralight tags. -- Unlock Mifare Ultralight tags with PIN. +- Lock/unlock Mifare Ultralight tags with PIN. - Read Mifare Ultralight tags. - Write Mifare Ultralight tags. - Check if NFC is enabled on the device. @@ -57,6 +57,10 @@ Available methods: * [mifare.read](#mifareread) * [mifare.write](#mifarewrite) * [mifare.unlock](#mifareunlock) +* [mifare.lockNTAG212](#mifarelockntag212) +* [mifare.lockMF0UL11](#mifarelockmf0ul11) +* [mifare.lockMF0UL21](#mifarelockmf0ul21) +* [mifare.lock](#mifarelock) #### mifare.enabled `mifare.enabled(success, failure)` @@ -129,6 +133,65 @@ Tries to unlock the tag. Parameter `pin` should be a number. window.mifare.unlock(0x1234, (response) => alert('Unlocked successfully'), err => alert(`Couldn't unlock because ${err}`)); ``` +#### mifare.lockNTAG212 +`mifare.lockNTAG212(firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, failure)` + +Tries to lock the tag of type `NTAG212`. For other tag types see the other methods starting with word `lock`. + +For parameter details see the options table under [`parameters in lock method`](Parameters). + +##### Example +```javascript +window.mifare.lockMF0UL11(37, 0x1234, true, 0, () => alert('Locked successfully'), err => alert(`Couldn't lock because ${err}`)); +``` + +#### mifare.lockMF0UL11 +`mifare.lockMF0UL11(firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, failure)` + +Tries to lock the tag of type `MF0UL11`. For other tag types see the other methods starting with word `lock`. + +For parameter details see the options table under [`parameters in lock method`](Parameters). + +##### Example +```javascript +window.mifare.lockMF0UL11(37, 0x1234, true, 0, () => alert('Locked successfully'), err => alert(`Couldn't lock because ${err}`)); +``` + +#### mifare.lockMF0UL21 +`mifare.lockMF0UL21(firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, failure)` + +Tries to lock the tag of type `MF0UL21`. For other tag types see the other methods starting with word `lock`. + +For parameter details see the options table under [`parameters in lock method`](Parameters). + +##### Example +```javascript +window.mifare.lockMF0UL21(37, 0x1234, true, 0, () => alert('Locked successfully'), err => alert(`Couldn't lock because ${err}`)); +``` + +#### mifare.lock +`mifare.lock(pin, success, failure)` + +Tries to lock the tag. + +*Please note that this command is the raw command used by the above vendor-specific ones. You need to know the pages you want to be using to use this method.* + +##### Parameters +*pinPage*: Page number for the PIN setting page (e.g. `39`) +*pinAckPage*: Page number for the PIN acknowledgement page (e.g. `40`) +*protectionPage*: Page number for the protection page (e.g. `38`) +*firstPageToBeProtectedPage*: Page number for the first page to be protected page (e.g. `37`) + +*firstPageToBeProtected*: Page number from which onwards to enable the protection (e.g. `41`) +*pin*: Pin to lock the tag with (e.g. 0x1234) +*protectAlsoReads*: Whether the reads should be protected along with writes (`false` for only protecting writes, `read` for protecting reads and writes) +*authenticationTryLimit*: How many times unlocking can be tried with invalid PIN. Value should be between 0-7. 0 means no limit is applied. + +##### Example +```javascript +window.mifare.lock(, () => alert('Locked successfully'), err => alert(`Couldn't lock because ${err}`)); +``` + ## FAQ *Q: Why is there no version to iOS or Windows Phone?* @@ -147,5 +210,9 @@ A: Not yet unfortunately. It is something on the todo list for sure, though. A: I would be happy to take in a Pull Request for this. It seemed somewhat cumbersome to implement.. Maybe at some point I will find the motivation to add it. +*Q: What is the difference between the lock methods?* + +A: Different tag types use different page numbers. For example `NTAG212` tags use pages numbered 39, 40, 38 and 37. These pages can all be adjusted by using the "raw" `lock` method but for your convenience there exists separate methods for different tag types that use the default page numbers. + ## Kudos This plugin is heavily influenced by the excellent work done on [PhoneGap NFC Plugin](https://github.com/chariotsolutions/phonegap-nfc). Thank you for the effort you have put into it over the years. diff --git a/package.json b/package.json index ffbb5fe..e9b35cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-mifare-ultralight", - "version": "1.0.3", + "version": "1.1.0", "description": "Provides Mifare Ultralight functionality for Cordova-based applications", "main": "www/cordova-plugin-mifare-ultralight.js", "scripts": { diff --git a/plugin.xml b/plugin.xml index 9fc5984..2fe2a48 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - cordova-plugin-mifare-ultralight diff --git a/src/android/CordovaPluginMifareUltralight.java b/src/android/CordovaPluginMifareUltralight.java index 474dd2f..febf936 100644 --- a/src/android/CordovaPluginMifareUltralight.java +++ b/src/android/CordovaPluginMifareUltralight.java @@ -1,24 +1,20 @@ package fi.roopehakulinen.CordovaPluginMifareUltralight; -import org.apache.cordova.*; - -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.content.IntentFilter; import android.nfc.NfcAdapter; import android.nfc.Tag; -import android.os.Bundle; -import android.os.Parcelable; import android.util.Log; +import org.apache.cordova.*; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; /** * This class echoes a string called from JavaScript. @@ -102,6 +98,37 @@ public boolean execute(String action, JSONArray args, final CallbackContext call final int pin = Integer.parseInt(arg0); this.unlock(callbackContext, pin); return true; + } else if (action.equals("lock")) { + final String arg0 = args.getString(0); + final String arg1 = args.getString(1); + final String arg2 = args.getString(2); + final String arg3 = args.getString(3); + final String arg4 = args.getString(4); + final String arg5 = args.getBoolean(5); + final String arg6 = args.getBoolean(6); + final String arg7 = args.getString(7); + + final int pinPage = Integer.parseInt(arg0) + final int pinAckPage = Integer.parseInt(arg1) + final int protectionPage = Integer.parseInt(arg2) + final int firstPageToBeProtectedPage = Integer.parseInt(arg3) + final int firstPageToBeProtected = Integer.parseInt(arg4) + final int pin = Integer.parseInt(arg5) + final boolean protectAlsoReads = arg6, + final int authenticationTryLimit = Integer.parseInt(arg7) + + this.lock( + callbackContext, + pinPage, + pinAckPage, + protectionPage, + firstPageToBeProtectedPage, + firstPageToBeProtected, + pin, + protectAlsoReads, + authenticationTryLimit + ); + return true; } return false; } @@ -244,6 +271,34 @@ public void run() { }); } + private void lock(final CallbackContext callbackContext, final int pin) { + cordova.getThreadPool().execute(new Runnable() { + @Override + public void run() { + if (getIntent() == null) { // Lost Tag + clean(callbackContext, "No tag available."); + return; + } + + final Tag tag = savedIntent.getParcelableExtra(NfcAdapter.EXTRA_TAG); + if (tag == null) { + clean(callbackContext, "No tag available."); + return; + } + try { + final boolean success = mifareUltralight.lockWithPin(page, pin); + if (success) { + callbackContext.success(); + } else { + callbackContext.error("Locking failed."); + } + } catch (final Exception e) { + clean(callbackContext, e); + } + } + }); + } + private void fireTagEvent(Tag tag, String name) { String command = MessageFormat.format(javaScriptEventTemplate, name, byteArrayToJSON(tag.getId())); this.webView.sendJavascript(command); @@ -362,7 +417,7 @@ private void setIntent(Intent intent) { private String bytesToHex(final byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; - for ( int j = 0; j < bytes.length; j++ ) { + for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; @@ -375,7 +430,7 @@ private static byte[] hexStringToByteArray(String s) { byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) - + Character.digit(s.charAt(i+1), 16)); + + Character.digit(s.charAt(i + 1), 16)); } return data; } diff --git a/src/android/MifareUltralight.java b/src/android/MifareUltralight.java index 654ac8f..14324aa 100644 --- a/src/android/MifareUltralight.java +++ b/src/android/MifareUltralight.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Arrays; public class MifareUltralight { private android.nfc.tech.MifareUltralight mifare = null; @@ -35,6 +36,59 @@ public boolean unlockWithPin(int pin) throws Exception { return false; } + public boolean lockWithPin( + int pinPage, + int pinAckPage, + int protectionPage, + int firstPageToBeProtectedPage, + int firstPageToBeProtected, + int pin, + boolean protectAlsoReads, + int authenticationTryLimit + ) throws Exception { + byte[] pack; + // 1. Write the PIN + final byte[] pinAsByteArray = intToByteArray(pin); + byte[] response = mifare.writePage(page, pinAsByteArray); + if ((response != null) && (response.length >= 2)) { + pack = Arrays.copyOf(response, 2); + } else { + return false; + } + // 2. Write the acknowledgement + byte[] data = {pack[0], pack[1], (byte) 0, (byte) 0}; + mifare.writePage(pinAckPage, data); + + // 3. Read the protection page to be able to only modify certain bits and then write it again + response = mifare.readPages(protectionPage); + if ((response != null) && (response.length >= 16)) { + data = { + (byte) ((response[0] & 0x078) | (protectAlsoReads ? 0x080 : 0x000) | (authenticationTryLimit & 0x007)), + response[1], // Keep old value for byte 1 + response[2], // Keep old value for byte 2 + response[3] // Keep old value for byte 3 + }; + mifare.writePage(protectionPage, data); + } + + // 4. Read the page to be able to only modify certain bits and then Write first page to be protected + response = mifare.readPages(firstPageToBeProtectedPage); + if ((response != null) && (response.length >= 16)) { + data = { + response[0], // Keep old value for byte 0 + response[1], // Keep old value for byte 1 + response[2], // Keep old value for byte 2 + (byte) (firstPageToBeProtected & 0x0ff) + }; + response = mifare.writePage(firstPageToBeProtectedPage, data); + if ((response != null) && (response.length >= 2)) { + return true; + } + } + + return false; + } + public byte[] read(int pageOffset) throws Exception { if (mifare == null || !mifare.isConnected()) { throw new Exception(); diff --git a/www/cordova-plugin-mifare-ultralight.js b/www/cordova-plugin-mifare-ultralight.js index 86d92ae..6df0dc9 100644 --- a/www/cordova-plugin-mifare-ultralight.js +++ b/www/cordova-plugin-mifare-ultralight.js @@ -1,30 +1,66 @@ var exec = require('cordova/exec'); -exports.enabled = function(success, error) { +exports.enabled = function (success, error) { exec(success, error, "cordova-plugin-mifare-ultralight", "enabled", []); }; -exports.connect = function(success, error) { +exports.connect = function (success, error) { exec(success, error, "cordova-plugin-mifare-ultralight", "connect", []); }; -exports.disconnect = function(success, error) { +exports.disconnect = function (success, error) { exec(success, error, "cordova-plugin-mifare-ultralight", "disconnect", []); }; -exports.isConnected = function(success, error) { +exports.isConnected = function (success, error) { exec(success, error, "cordova-plugin-mifare-ultralight", "isConnected", []); }; -exports.read = function(page, success, error) { +exports.read = function (page, success, error) { exec(success, error, "cordova-plugin-mifare-ultralight", "read", [page]); }; -exports.write = function(page, data, success, error) { +exports.write = function (page, data, success, error) { exec(success, error, "cordova-plugin-mifare-ultralight", "write", [page, data]); }; -exports.unlock = function(pin, success, error) { +exports.unlock = function (pin, success, error) { exec(success, error, "cordova-plugin-mifare-ultralight", "unlock", [pin]); +}; + +exports.lock = function ( + pinPage, + pinAckPage, + protectionPage, + firstPageToBeProtectedPage, + firstPageToBeProtected, + pin, + protectAlsoReads, + authenticationTryLimit, + success, + error +) { + exec(success, error, "cordova-plugin-mifare-ultralight", "lock", [ + pinPage, + pinAckPage, + protectionPage, + firstPageToBeProtectedPage, + firstPageToBeProtected, + pin, + protectAlsoReads, + authenticationTryLimit + ]); +}; + +exports.lockNTAG212 = function (firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error) { + exports.lock(39, 40, 38, 37, firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error); +}; + +exports.lockMF0UL11 = function (firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error) { + exports.lock(12, 13, 11, 10, firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error); +}; + +exports.lockMF0UL21 = function (firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error) { + exports.lock(27, 28, 26, 25, firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error); }; \ No newline at end of file From ad445965f3f0972a390af89654b56a24dd8a3b5b Mon Sep 17 00:00:00 2001 From: Roope Hakulinen Date: Wed, 19 Sep 2018 14:08:40 +0100 Subject: [PATCH 2/5] Fix the documentation. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3c827bb..4ef3f74 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ window.mifare.lockMF0UL21(37, 0x1234, true, 0, () => alert('Locked successfully' ``` #### mifare.lock -`mifare.lock(pin, success, failure)` +`mifare.lock(pinPage, pinAckPage, protectionPage, firstPageToBeProtectedPage, firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, failure)` Tries to lock the tag. @@ -189,7 +189,7 @@ Tries to lock the tag. ##### Example ```javascript -window.mifare.lock(, () => alert('Locked successfully'), err => alert(`Couldn't lock because ${err}`)); +window.mifare.lock(21, 22, 23, 24, 37, 0x1234, true, 0, () => alert('Locked successfully'), err => alert(`Couldn't lock because ${err}`)); ``` ## FAQ From ea7213b2963c6be01fe7d455945d443702f1fedc Mon Sep 17 00:00:00 2001 From: Roope Hakulinen Date: Thu, 7 Feb 2019 10:36:18 +0000 Subject: [PATCH 3/5] Add missing semicolons. --- src/android/CordovaPluginMifareUltralight.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/android/CordovaPluginMifareUltralight.java b/src/android/CordovaPluginMifareUltralight.java index febf936..5c41a03 100644 --- a/src/android/CordovaPluginMifareUltralight.java +++ b/src/android/CordovaPluginMifareUltralight.java @@ -108,14 +108,14 @@ public boolean execute(String action, JSONArray args, final CallbackContext call final String arg6 = args.getBoolean(6); final String arg7 = args.getString(7); - final int pinPage = Integer.parseInt(arg0) - final int pinAckPage = Integer.parseInt(arg1) - final int protectionPage = Integer.parseInt(arg2) - final int firstPageToBeProtectedPage = Integer.parseInt(arg3) - final int firstPageToBeProtected = Integer.parseInt(arg4) - final int pin = Integer.parseInt(arg5) - final boolean protectAlsoReads = arg6, - final int authenticationTryLimit = Integer.parseInt(arg7) + final int pinPage = Integer.parseInt(arg0); + final int pinAckPage = Integer.parseInt(arg1); + final int protectionPage = Integer.parseInt(arg2); + final int firstPageToBeProtectedPage = Integer.parseInt(arg3); + final int firstPageToBeProtected = Integer.parseInt(arg4); + final int pin = Integer.parseInt(arg5); + final boolean protectAlsoReads = arg6; + final int authenticationTryLimit = Integer.parseInt(arg7); this.lock( callbackContext, From db29d446254b858ade7d26fc9818b5e4d4ddb9ce Mon Sep 17 00:00:00 2001 From: Roope Hakulinen Date: Thu, 7 Feb 2019 10:37:12 +0000 Subject: [PATCH 4/5] We are protecting reads, not writes. --- README.md | 6 +++--- www/cordova-plugin-mifare-ultralight.js | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4ef3f74..46d3274 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ window.mifare.unlock(0x1234, (response) => alert('Unlocked successfully'), err = ``` #### mifare.lockNTAG212 -`mifare.lockNTAG212(firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, failure)` +`mifare.lockNTAG212(firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, failure)` Tries to lock the tag of type `NTAG212`. For other tag types see the other methods starting with word `lock`. @@ -146,7 +146,7 @@ window.mifare.lockMF0UL11(37, 0x1234, true, 0, () => alert('Locked successfully' ``` #### mifare.lockMF0UL11 -`mifare.lockMF0UL11(firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, failure)` +`mifare.lockMF0UL11(firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, failure)` Tries to lock the tag of type `MF0UL11`. For other tag types see the other methods starting with word `lock`. @@ -158,7 +158,7 @@ window.mifare.lockMF0UL11(37, 0x1234, true, 0, () => alert('Locked successfully' ``` #### mifare.lockMF0UL21 -`mifare.lockMF0UL21(firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, failure)` +`mifare.lockMF0UL21(firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, failure)` Tries to lock the tag of type `MF0UL21`. For other tag types see the other methods starting with word `lock`. diff --git a/www/cordova-plugin-mifare-ultralight.js b/www/cordova-plugin-mifare-ultralight.js index 6df0dc9..c48b733 100644 --- a/www/cordova-plugin-mifare-ultralight.js +++ b/www/cordova-plugin-mifare-ultralight.js @@ -53,14 +53,14 @@ exports.lock = function ( ]); }; -exports.lockNTAG212 = function (firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error) { - exports.lock(39, 40, 38, 37, firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error); +exports.lockNTAG212 = function (firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, error) { + exports.lock(39, 40, 38, 37, firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, error); }; -exports.lockMF0UL11 = function (firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error) { - exports.lock(12, 13, 11, 10, firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error); +exports.lockMF0UL11 = function (firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, error) { + exports.lock(12, 13, 11, 10, firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, error); }; -exports.lockMF0UL21 = function (firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error) { - exports.lock(27, 28, 26, 25, firstPageToBeProtected, pin, protectAlsoWrites, authenticationTryLimit, success, error); +exports.lockMF0UL21 = function (firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, error) { + exports.lock(27, 28, 26, 25, firstPageToBeProtected, pin, protectAlsoReads, authenticationTryLimit, success, error); }; \ No newline at end of file From a2951d6339b7dff22108e73f8ef646c313da98c0 Mon Sep 17 00:00:00 2001 From: Roope Hakulinen Date: Thu, 7 Feb 2019 14:30:52 +0000 Subject: [PATCH 5/5] Use long over int for pin everywhere. --- src/android/CordovaPluginMifareUltralight.java | 4 ++-- src/android/MifareUltralight.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/android/CordovaPluginMifareUltralight.java b/src/android/CordovaPluginMifareUltralight.java index 7af0d69..5a94a54 100644 --- a/src/android/CordovaPluginMifareUltralight.java +++ b/src/android/CordovaPluginMifareUltralight.java @@ -113,7 +113,7 @@ public boolean execute(String action, JSONArray args, final CallbackContext call final int protectionPage = Integer.parseInt(arg2); final int firstPageToBeProtectedPage = Integer.parseInt(arg3); final int firstPageToBeProtected = Integer.parseInt(arg4); - final int pin = Integer.parseInt(arg5); + final long pin = Long.parseLong(arg5); final boolean protectAlsoReads = arg6; final int authenticationTryLimit = Integer.parseInt(arg7); @@ -271,7 +271,7 @@ public void run() { }); } - private void lock(final CallbackContext callbackContext, final int pin) { + private void lock(final CallbackContext callbackContext, final long pin) { cordova.getThreadPool().execute(new Runnable() { @Override public void run() { diff --git a/src/android/MifareUltralight.java b/src/android/MifareUltralight.java index 62cfd1c..43b727d 100644 --- a/src/android/MifareUltralight.java +++ b/src/android/MifareUltralight.java @@ -42,13 +42,13 @@ public boolean lockWithPin( int protectionPage, int firstPageToBeProtectedPage, int firstPageToBeProtected, - int pin, + long pin, boolean protectAlsoReads, int authenticationTryLimit ) throws Exception { byte[] pack; // 1. Write the PIN - final byte[] pinAsByteArray = intToByteArray(pin); + final byte[] pinAsByteArray = longToByteArray(pin); byte[] response = mifare.writePage(page, pinAsByteArray); if ((response != null) && (response.length >= 2)) { pack = Arrays.copyOf(response, 2);