Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@martijnthe/nfc-pcsc
Advanced tools
Easy reading and writing NFC tags and cards in Node.js
Built-in support for auto-reading card UIDs and reading tags emulated with Android HCE.
NOTE: Reading tag UID and methods for writing and reading tag content depend on NFC reader commands support. It is tested to work with ACR122 USB reader but it should work with all PC/SC compliant devices.
When detecting tags does not work see Alternative usage.
This library uses pcsclite native bindings pokusew/node-pcsclite under the hood.
Psst! Problems upgrading to 0.6.0? Check out this migration note.
Requirements: Node.js 7+ (it might work under 6.x but it is not tested)
Note: This library uses system PC/SC API. On Windows and macOS it works out of the box, but on Linux you have to do some steps as described here
Using npm:
npm install nfc-pcsc --save
or with yarn:
yarn add nfc-pcsc
When a NFC tag (card) is attached to the reader, the following is done:
it tries to find out the standard of card (TAG_ISO_14443_3
or TAG_ISO_14443_4
)
it will connect to the card, so any other card specific commands could be send
handling of card
when autoProcessing
is true (default value) it will handle card by the standard:
TAG_ISO_14443_3
(Mifare Ultralight, 1K ...): sends GET_DATA command to retrieve card UID
TAG_ISO_14443_4
(e.g.: Andorid HCE): sends SELECT_APDU command to retrive data by file
then card
event is fired, for which you can listen and then you can read or write data on the card
see Basic usage how to do it
when autoProcessing
is false (default value) it will only fire card
event
then you can send whatever commands you want using reader.transmit
method
see Alternative usage how to do it
you can read data, write data and send other commands
Running examples locally
If you want see it in action, clone this repository, install dependencies with npm and run
npm run example
.
git clone https://github.com/pokusew/nfc-pcsc.git npm install npm run example
You can use this library in any Node.js 7+ environment (even in an Electron app).
// in ES6
import { NFC } from 'nfc-pcsc';
// without Babel in ES2015
const { NFC } = require('nfc-pcsc');
const nfc = new NFC(); // optionally you can pass logger
nfc.on('reader', reader => {
console.log(`${reader.reader.name} device attached`);
// needed for reading tags emulated with Android HCE
// custom AID, change according to your Android for tag emulation
// see https://developer.android.com/guide/topics/connectivity/nfc/hce.html
reader.aid = 'F222222222';
reader.on('card', card => {
// card is object containing following data
// [always] String type: TAG_ISO_14443_3 (standard nfc tags like Mifare) or TAG_ISO_14443_4 (Android HCE and others)
// [always] String standard: same as type
// [only TAG_ISO_14443_3] String uid: tag uid
// [only TAG_ISO_14443_4] Buffer data: raw data from select APDU response
console.log(`${reader.reader.name} card detected`, card);
});
reader.on('card.off', card => {
console.log(`${reader.reader.name} card removed`, card);
});
reader.on('error', err => {
console.log(`${reader.reader.name} an error occurred`, err);
});
reader.on('end', () => {
console.log(`${reader.reader.name} device removed`);
});
});
nfc.on('error', err => {
console.log('an error occurred', err);
});
You can disable auto processing of tags and process them yourself. It may be useful when you are using other than ACR122 USB reader or non-standard tags.
// in ES6
import { NFC } from 'nfc-pcsc';
// without Babel in ES2015
const { NFC } = require('nfc-pcsc');
const nfc = new NFC(); // optionally you can pass logger
nfc.on('reader', reader => {
// disable auto processing
reader.autoProcessing = false;
console.log(`${reader.reader.name} device attached`);
// needed for reading tags emulated with Android HCE
// custom AID, change according to your Android for tag emulation
// see https://developer.android.com/guide/topics/connectivity/nfc/hce.html
// reader.aid = 'F222222222';
reader.on('card', card => {
// card is object containing following data
// String standard: TAG_ISO_14443_3 (standard nfc tags like Mifare) or TAG_ISO_14443_4 (Android HCE and others)
// String type: same as standard
// Buffer atr
console.log(`${reader.reader.name} card inserted`, card);
// you can use reader.transmit to send commands and retrieve data
// see https://github.com/pokusew/nfc-pcsc/blob/master/src/Reader.js#L291
});
reader.on('card.off', card => {
console.log(`${reader.reader.name} card removed`, card);
});
reader.on('error', err => {
console.log(`${reader.reader.name} an error occurred`, err);
});
reader.on('end', () => {
console.log(`${reader.reader.name} device removed`);
});
});
nfc.on('error', err => {
console.log('an error occurred', err);
});
You can read from and write to numerous NFC tags including Mifare Ultralight (tested), Mifare Classic, Mifare DESFire, ...
Actually, you can even read/write any possible non-standard NFC tag and card, via sending APDU commands according card's technical documentation via
reader.transmit
.
Here is a simple example showing reading and writing data to simple card without authenticating (e.g. Mifare Ultralight):
See Basic usage how to set up reader or look here for full code
reader.on('card', async card => {
console.log();
console.log(`card detected`, card);
// example reading 12 bytes assuming containing text in utf8
try {
// reader.read(blockNumber, length, blockSize = 4, packetSize = 16)
const data = await reader.read(4, 12); // starts reading in block 4, continues to 5 and 6 in order to read 12 bytes
console.log(`data read`, data);
const payload = data.toString(); // utf8 is default encoding
console.log(`data converted`, payload);
} catch (err) {
console.error(`error when reading data`, err);
}
// example write 12 bytes containing text in utf8
try {
const data = Buffer.allocUnsafe(12);
data.fill(0);
const text = (new Date()).toTimeString();
data.write(text); // if text is longer than 12 bytes, it will be cut off
// reader.write(blockNumber, data, blockSize = 4)
await reader.write(4, data); // starts writing in block 4, continues to 5 and 6 in order to write 12 bytes
console.log(`data written`);
} catch (err) {
console.error(`error when writing data`, err);
}
});
📦📦📦 You can find more examples in examples folder, including:
Feel free to open pull request, if you have any useful example, that you'd like to add.
There was a breaking change in 0.6.0, as the default export was removed (because of non-standard behaviour of ES6 modules in ES5 env (see #12 and v0.6.0 release changelog)).
You have to update all requires or imports of this library to the following (note the brackets around NFC):
// in ES6 environment
import { NFC } from 'nfc-pcsc';
// in ES2015 environment
const { NFC } = require('nfc-pcsc');
Yes, you can! It works well.
But please note, that this library uses Node Native Modules (underlying library pokusew/node-pcsclite which provides access to PC/SC API).
Read carefully Using Native Node Modules guide in Electron documentation to fully understand the problematic.
Note, that because of Node Native Modules, you must build your app on target platform (you must run Windows build on Windows machine, etc.).
You can use CI/CD server to build your app for certain platforms.
For Windows, I recommend you to use AppVeyor.
For macOS and Linux build, there are plenty of services to choose from, for example CircleCI, Travis CI CodeShip.
Yes, you can! But as this library uses Node Native Modules, you must change some config in package.json
and webpack.config.js
as described in this comment.
No, you don't have to. This library works great in any Node.js 7+ environment (even in an Electron app).
Psst! Instead of using async/await (like in examples), you can use Promises.
reader .read(...) .then(data => ...) .catch(err => ...))
Internally it uses Babel under the hood to transpile things, that are not supported in Node.js v7 (e.g.: import/export). The transpiled code (in the dist folder) is then published into npm and when you install and require the library, it requires the transpiled code, so you don't have to worry about anything.
// in ES6 environment
import { NFC } from 'nfc-pcsc';
// in ES2015 environment
const { NFC } = require('nfc-pcsc');
If you want to import uncompiled source and transpile it yourself (not recommended), you can do it as follows:
import { NFC } from 'nfc-pcsc/src';
Yes, you can! You can read raw byte card data with reader.read
method, and then you can parse it with any NDEF parser, e.g. TapTrack/NdefJS.
Psst! There is also an example (ndef.js), but it is not finished yet. Feel free to contribute.
No worry, just check that you import/require the library like this (note the brackets around NFC):
// in ES6 environment
import { NFC } from 'nfc-pcsc';
// in ES2015 environment
const { NFC } = require('nfc-pcsc');
Take a a look at How do I require/import this library? section for more info.
Note, that
const NFC = require('nfc-pcsc');
orimport NFC from 'nfc-pcsc'
(NFC without brackets) won't work, because there is no default export.
It was removed for non-standard behaviour of ES6 modules in ES5 env (see #12 and v0.6.0 release changelog)
CONNECT_MODE_DIRECT
No worry, just needs a proper configuration, see explanation and instructions here.
No worry, you have probably modified a sector trailer instead of a data block, see explanation and instructions here.
FAQs
Easy reading and writing NFC tags and cards
We found that @martijnthe/nfc-pcsc demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.