nilezon wrote:Good find!
I did see a key expansion algorithm but I didn't bother to "decode" it.
Also, I did see some unreachable code in the key/pack assembler, so I figured they used some standard algorithm, but I didn't understand it was RC5. Instead I tried to simplify the code as much as possible, removing the unused code and using the expanded integers.
Hi nilezon,
Just for the record. ;-) Finally I can confirm that the the PASS and PACK generation use RC5 enryption with the key "915F4619BE41B2516355A50110A9CE91"
One thing I down understand, why they used that good know Key??
If you google for it, you will find a lot hits.
so in C# I do it like this:
private static byte[] Magic_RC5_Key = { 0x91, 0x5F, 0x46, 0x19, 0xBE, 0x41, 0xB2, 0x51, 0x63, 0x55, 0xA5, 0x01, 0x10, 0xA9, 0xCE, 0x91 };
static InitNfcKey()
{
// initialization with our key
CryptoRC5.RC5Engine.RC5_Init(Magic_RC5_Key);
}
public static Byte[] GetPASS(Byte[] uid)
{
// Buffer for rotated UID
byte[] buffer_In = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//-- Part 1 -------------------------------------//
// calculate rotation offset
int rot_offset = ((uid[1] + uid[3] + uid[5]) & 7);
// rotate the UID
for (uint i = 0; i < 7; i++)
buffer_In[(i + rot_offset) & 7] = uid[i];
//-- Part 2 -------------------------------------//
// call RC5 Encryption
byte[] buffer_Out = CryptoRC5.RC5Engine.RC5_Encrypt(buffer_In);
//-- Part 3 -------------------------------------//
//Calc PASS
long PASS = 0; //Key as int
// calculate rotation offset
rot_offset = ((buffer_Out[0] + buffer_Out[2] + buffer_Out[4] + buffer_Out[6]) & 3);
for (uint i = 0; i < 4; i++)
PASS = (buffer_Out[i + rot_offset] & 0xFF) + (PASS << 8);
return BitConverter.GetBytes(PASS);
}
public static Byte[] GetPack(Byte[] uid)
{
// Buffer for rotated UID
byte[] buffer_In = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//-- Part 1 -------------------------------------//
// calculate rotation offset
int rot_offset = ((uid[2] + uid[5]) & 7);
// rotate the UID
for (uint i = 0; i < 7; i++)
buffer_In[(i + rot_offset) & 7] = uid[i];
//-- Part 2 -------------------------------------//
// call RC5 Encryption
byte[] buffer_Out = CryptoRC5.RC5Engine.RC5_Encrypt(buffer_In);
//-- Part 3 -------------------------------------//
//Calc PACK
long PACK = 0;
for (uint i = 0; i < 8; i++)
PACK = ((buffer_Out[i] & 0xFF) * 13) + PACK;
Byte[] packBytes = BitConverter.GetBytes((PACK & 0xFFFF) ^ 0x5555);
return (new Byte[2] { packBytes[0], packBytes[1] });
}