Mifare Change KEY A and B - rfid

I have an ACR122U Contactless NFC reader. I bought a lot of blank RFID Mifare 4k tags. Their default Authentication KEY A and KEY B is FF FF FF FF FF FF.
Now I want to change them to something else. I'm using APDU structure. I'm sending commands like this and it works well:
byte[] baData = { 0x01, 0x00, (byte)i, 0x60, 0x00 };
APDUCommand apdux3 = new APDUCommand((byte)0xFF, (byte)0x86, (byte)0x00, (byte)0x00, baData, 0x05);
It works well. I don't know what this interface and model means, but using this type and structure, I want to change KEY A and KEY B.
Please help me. I can't find any document.
Regards

That's true, chips are delivered with default key FF FF FF FF FF FF for key A and B.
To change them you have to authenticate the card with the correct access bits.
Note: the Mifare key is composed as follow:
6 byte for key A
4 byte for Access Bits
6 byte for key B which is optional and can be set to 00 or any other value
To change your keys you have to authenticate the Sector Trailer and the write your new keys + new access conditions if you want to change them too.
Example
New key A = 00 11 22 33 44 55
Access bits not overwritten
Key B not used (so FF FF FF FF FF FF)
=> Write to Sector Trailer 00 11 22 33 44 55 FF 0F 00 FF FF FF FF FF FF FF
Further details are on the NXP website available or directly at the following link: https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf
A default Access Bits is usually FF 0F 00 that allow to write and read each block and to read and write key B.

Related

how to convert buffer stream data from fingerprint capture to byte array in nodejs

How can i convert buffer data coming from fingerprint capture to byte array in nodejs
<Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 ...>
var arrByte = Uint8Array.from(data)
Also, see this similar question and the docs for Buffer.

Error 0x6700 in securechannel.processSecurity(apdu)

I want to generate gp secure channel 01. my trace is:
Send: 80 50 00 00 08 00 00 00 00 00 00 00 00
Recv: 00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
so I have :
Card challenge= 00 02 0E 5A 8F F4 57 DD
Host challenge=00 00 00 00 00 00 00 00
according SPC01: image
Derivation data== 8F F4 57 DD 00 00 00 00 00 02 0E 5A 00 00 00 00
IV=0000000000000000
c_ENC: 404142434445464748494A4B4C4D4E4F
according this image and 3Des online
session s_ENC= C72F032C8BAD55D4D2579295CCF0A6CA
now :
hot-auth_data = card challenge + host challenge + pad
host-auth= 00020E5A8FF457DD00000000000000008000000000000000
s_ENC=C72F032C8BAD55D4D2579295CCF0A6CA
IV=0000000000000000
===========
result= 93CC77E144488A031BFFCCC62EB3B5C233A485F8255FE90E
Host cryptogram= 33A485F8255FE90E
but when I send :
848200000833A485F8255FE90E
I have error 0x6700 in method SDInstruction in line
short len = sc.processSecurity(apdu);
public void process(APDU apdu) throws ISOException {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
switch (buffer[ISO7816.OFFSET_INS]) {
case ISO7816.INS_SELECT:
select();
return;
case INS_INIT_UPDATE:
case INS_EXT_AUTH:
SDInstruction(apdu);
break;
}
}
private void SDInstruction(APDU apdu)
{
byte[] buf = apdu.getBuffer();
byte cla = buf[ISO7816.OFFSET_CLA];
byte ins = buf[ISO7816.OFFSET_INS];
apdu.setIncomingAndReceive();
if(ins == INS_INIT_UPDATE)
sc = GPSystem.getSecureChannel();
short len = sc.processSecurity(apdu);
apdu.setOutgoing();
apdu.setOutgoingLength(len);
apdu.sendBytes(ISO7816.OFFSET_CDATA, (short) len);
}
Your card is using SCP02 and not SCP01.
Given the response to the INITIALIZE UPDATE command:
00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
The highlighted part is the "Key Information" which contains:
"Key Version Number" -- in your trace 0xFF
"Secure Channel Protocol Identifier" -- in your trace it is 0x02 indicating SCP02
See the Global Platform Card Specification for further reference (sections describing the INITIALIZE UPDATE command).
So you need to establish the secure channel with the card according to the SCP02.
Some additional (random) notes:
be sure to check the "i" secure channel parameter encoded inside the "Card Recognition Data" (tag '64') as well
you might want to look at the method GlobalPlatform.openSecureChannel() and the inner class GlobalPlatform.SCP0102Wrapper in the GlobalPlatformPro tool source code
Good luck!
According to the GlobalPlatform specification, the EXTERNAL AUTHENTICATE command has to include the host cryptogram as well as the MAC. Both are 8 bytes long, hence, your command should be 16 bytes in total.
If you want to implement the generation of this MAC value yourself, you can follow the description in the GlobalPlatform spec. But I suggest you to make use of available open source implementation. For example: GPJ is a Java implementation of the GlobalPlatform specification and has all commands that you need. You can take a look at the class GlobalPlatformService, where you will find the implementation of the secure channel protocol. GPDroid (github.com/mobilesec/secure-element-gpdroid) is a wrapper for this project on Android.

ACR1222L FF 82 Load Authentication Keys fails with 63 00 Operation Failed

I'm using ACR1222L NFC smartcard reader with Mifare Plus cards (Security Level 0 as of now; manufacturer default keys A and B). I tried a variety of commands to load authentication key into the reader:
FF 82 00 00 06 FF FF FF FF FF FF
FF 82 00 01 06 FF FF FF FF FF FF
FF 82 20 00 06 FF FF FF FF FF FF
FF 82 00 00 06 A0 A1 A2 A3 A4 A5
FF 82 00 00 06 D3 F7 D3 F7 D3 F7
... and others ...
All of them are returning the error status:
63 00 (Operation Failed)
What could be wrong? I have searched long and wide for a hint, but many other questions are about failed authentication or failed read after successfully loading authentication key with one of the above commands, and they are often based on a different device (ACR122U).
I noticed that the reader does not even respond to the command when a card is not present. Should a card be present on the reader for it to load authentication key?
To be able to use the commands such as "Load Authentication Key", "Authentication (of a block)", Read, Write, Update, etc, the card has to be in Security Level 1 or higher.
There are certain commands to move the card from Security Level 0 to Security Level 1 by loading several relevant keys into the card. Please contact ACS to obtain these commands as they are not publicly documented.
(Additional Info)
Please try command-
0xFF 0x82 0x00 0x60 [key length] [ key value]
or
0xFF 0x82 0x00 0x61 [key length] [ key value]
Where 0x60 to use key Type A and 0x61 for key Type B.

Authenticate/Read/Write NFC Mifare Classic Using Private Key

With refrence to Michael Roland's answer, I am facing problems in changing the key of a Mifare Classic 4K card. I want to do the personalization of NFC cards using NFC reader ACR122U.
I have followed the steps defined in this answer, and successfully read and write the sector trailer block 11 (by reading I got the 2 access bytes and 1 general purpose byte), as
00 00 00 00 00 7F 07 88 40 00 00 00 00 00
Using these access bytes and the new keys KeyA (D6 DF 20 AE AE BC) and KeyB (D6 DF 20 AE AE BC), I generate 16 byte (D6 DF 20 AE AE BC ...), along with access bytes to change the sector keys. I.e. write to block 11 with following 16 bytes:
D6 DF 20 AE AE BC 7F 07 88 40 D6 DF 20 AE AE BC
The write command thus becomes
FF D6 00 11 10 D6 DF 20 AE AE BC 7F 07 88 40 D6 DF 20 AE AE BC
The command executed successfully but when I authenticated block 8 (1st block of same sector), using Key B (0x61) and key (1 or 0), the authentication failed and returns 0x63. Which means sector 2 becomes inaccessible.
Also after then read and write to that sector failed.
Also Android App NFCTagInfo shows following
Data (US-ASCII), Shows Sector 2: Read Failed!
Access Conditions : Sector 2 (Could not read access conditions!)

Would it be possible to read out physical keyboard strokes in node.js?

I have a node application which runs on a raspberry pi that keeps track of a bunch of UPnP-players (Sonos), which I would like to be able to control through a physical remote. I have a couple of airmouses, which has small keyboards as well as volume buttons that I would like to use.
I have tried to get a grip on how to read out physical key strokes on a linux machine, and come to the conclusion that I need to read events from the input device, which in my case would be:
/dev/input/by-id/usb-Dell_Dell_QuietKey_Keyboard-event-kbd
How to find the device and stuff like that is not a problem, the real issue is how to interpret the data that you read from it.
I know that you would receive a C struct, like this:
struct input_event {
struct timeval time;
unsigned short type;
unsigned short code;
unsigned int value;
};
But I'm not sure how I would go about reading this from node. If I could run an external app that would be triggered from pre-defined keystrokes, and then invoke an HTTP-request against my node, that would be my second option, a python script or some native daemon. I have however looked at some hotkey-daemons, but none of them worked.
If would of course be nice if I could contain it within node somehow.
EDIT: So I did some testing, and made a simple snippet:
var fs = require('fs');
var buffer = new Buffer(16);
fs.open('/dev/input/by-id/usb-HJT_Air_Mouse-event-kbd', 'r', function (err, fd) {
while (true) {
fs.readSync(fd, buffer, 0, 16, null);
console.log(buffer)
}
});
This outputs something like this (for space):
<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00>
<Buffer a4 3e 5b 51 c3 cf 03 00 01 00 39 00 01 00 00 00>
<Buffer a4 3e 5b 51 cb cf 03 00 00 00 00 00 00 00 00 00>
<Buffer a4 3e 5b 51 ba 40 06 00 04 00 04 00 2c 00 07 00>
<Buffer a4 3e 5b 51 cd 40 06 00 01 00 39 00 00 00 00 00>
<Buffer a4 3e 5b 51 d2 40 06 00 00 00 00 00 00 00 00 00>
I realize that the first four bytes are some sort of timestamp, and the following 3 bytes could be something like a micro/millisecond thing.
Another odd thing is that not all keypresses produces output, but a subsequent press might sent twice as much data, and most of the time it starts blasting out data which would stop after subsequent keypresses (or after about 20 seconds or so). I'm not really sure how to interpret that. I have tried to read the source for this daemon https://github.com/baskerville/shkd/blob/master but C is not my strongest language and I can't identify how he handles it (or if it should even be handled). And that daemon didn't even work for me (compiled it on a raspberry pi).
Well, let's have a look at that struct.
struct input_event {
struct timeval time;
unsigned short type;
unsigned short code;
unsigned int value;
};
A struct timeval has this structure:
struct timeval
{
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
};
The definition of those time types are
typedef signed long time_t;
typedef signed long suseconds_t;
A signed long is 4 bytes (well, not if you just follow the spec, but in practice, it is), so the first 8 bytes are a typestamp. Next, you have a type and a code. Both are short, so in practice, they're 2 bytes each. Now there's just the value left, and that's an int again, which will be four bytes. Also, a compiler could theoretically add padding between the fields here, but I'm pretty sure he won't.
So, first chop the bytes you've read into chunks of 4+4+2+2+4=16 bytes. Each of those chunks is an event. This fits your sample data. Next, extract the values from the buffer (as little endian values because you're on an ARM system – on a normal PC, you'd need big endian) and interpret the values. For instructions on how to do that, read http://www.mjmwired.net/kernel/Documentation/input/event-codes.txt. The values of the constants aren't written down there, but you can usually find those using grep -R NAME_OF_CONSTANT /usr/include.
Let's chop up
<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00>
as an example.
<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00>
| tv_sec | tv_usec |type |code | value |
tv_sec in hex is 0x515b3ea4 (reversed order because it's little endian), which is 1364934308 in decimal. A simple unix time converter reports that this means 02.04.2013 - 22:25:08. Looks good!
tv_usec is 0x0003cfab=249771, so actually, the event happened 249771 microseconds after that time.
Type is 0x0004=4. /usr/include/linux/input.h tells us that this is a EV_MSC.
Given the type, we can also see the the code, 0x0004=4, means MSC_SCAN.
The value is 0x0007002c. Turns up nowhere in input.h. Hmm.
I think what you're looking for is fs.createReadStream, so you can install some event handlers.
You can parse input events into structs by using the Buffer.readX routines:
var i = 0;
while((buf.length-i) >= 16) {
var event = {
tssec: buf.readUInt32LE(i+0),
tsusec: buf.readUInt32LE(i+4),
type: buf.readUInt16LE(i+8),
code: buf.readUInt16LE(i+10),
value: buf.readUInt32LE(i+12)
};
i += 16;
}

Resources