mirror of
https://gitlab.com/fabinfra/fabaccess/borepin.git
synced 2025-06-11 11:03:23 +02:00
BackUp
This commit is contained in:
44
NFC/Crypto/CRC32.cs
Normal file
44
NFC/Crypto/CRC32.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
|
||||
namespace NFC.Crypto
|
||||
{
|
||||
public class CRC32
|
||||
{
|
||||
public byte[] Calculate(byte[] data)
|
||||
{
|
||||
UInt32 crc32 = 0xFFFFFFFF;
|
||||
|
||||
crc32 = Calculate(data, crc32);
|
||||
|
||||
return BitConverter.GetBytes(crc32);
|
||||
}
|
||||
|
||||
public byte[] Calculate(byte[] cmd, byte[] data)
|
||||
{
|
||||
UInt32 crc32 = 0xFFFFFFFF;
|
||||
|
||||
crc32 = Calculate(cmd, crc32);
|
||||
crc32 = Calculate(data, crc32);
|
||||
|
||||
return BitConverter.GetBytes(crc32);
|
||||
}
|
||||
|
||||
public UInt32 Calculate(byte[] data, UInt32 crc32)
|
||||
{
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
crc32 ^= data[i];
|
||||
for (int b = 0; b < 8; b++)
|
||||
{
|
||||
bool b_Bit = (crc32 & 0x01) > 0;
|
||||
crc32 >>= 1;
|
||||
if (b_Bit)
|
||||
{
|
||||
crc32 ^= 0xEDB88320;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc32;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +1,13 @@
|
||||
using NFC.Crypto;
|
||||
using NFC.ISO7816_4;
|
||||
using NFC.Mifare_DESFire.Enums;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
using PCSC.Iso7816;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
|
||||
namespace NFC.Mifare_DESFire
|
||||
{
|
||||
|
||||
public class MIFARE_DESFire
|
||||
{
|
||||
// Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg
|
||||
@ -31,6 +28,9 @@ namespace NFC.Mifare_DESFire
|
||||
/// ICard Implementation used to transmit APDUCommands and recive APDUResponses
|
||||
/// </summary>
|
||||
private ICard _Card;
|
||||
|
||||
public byte[] _SessionKey;
|
||||
public byte[] _IV;
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
@ -43,7 +43,7 @@ namespace NFC.Mifare_DESFire
|
||||
byte[] key = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
key.[i] = 0;
|
||||
key[i] = 0;
|
||||
}
|
||||
|
||||
return key;
|
||||
@ -64,6 +64,63 @@ namespace NFC.Mifare_DESFire
|
||||
|
||||
}
|
||||
|
||||
public bool CheckKey(byte[] key)
|
||||
{
|
||||
try
|
||||
{
|
||||
GetKeyTypeDES(key);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Key Types used for DESFire Cards
|
||||
/// </summary>
|
||||
public enum KeyType
|
||||
{
|
||||
/// <summary>
|
||||
/// DES Key - 8 Byte - 64 Bit
|
||||
/// </summary>
|
||||
DES,
|
||||
|
||||
/// <summary>
|
||||
/// Triple DES Key with two DES Keys - 16 Byte - 128 Bit
|
||||
/// </summary>
|
||||
TDES_2K,
|
||||
|
||||
/// <summary>
|
||||
/// Triple DES Key with three DES Keys - 24 Byte - 192 Bit
|
||||
/// </summary>
|
||||
TDES_3K,
|
||||
|
||||
/// <summary>
|
||||
/// AES Key - 16 Byte - 128 Bit
|
||||
/// </summary>
|
||||
AES
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check the Key Length to get Type of DES/3DES Key
|
||||
/// </summary>
|
||||
public KeyType GetKeyTypeDES(byte[] key)
|
||||
{
|
||||
switch(key.Length)
|
||||
{
|
||||
case 8:
|
||||
return KeyType.DES;
|
||||
case 16:
|
||||
return KeyType.TDES_2K;
|
||||
case 24:
|
||||
return KeyType.TDES_3K;
|
||||
default:
|
||||
throw new ArgumentException(string.Format("No valid DES/3DES Key Size({0})", key.Length));
|
||||
}
|
||||
}
|
||||
|
||||
#region Methods for Crypto Operation
|
||||
/// <summary>
|
||||
/// Return a copy of the last Block of data
|
||||
@ -141,6 +198,23 @@ namespace NFC.Mifare_DESFire
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public byte[] xor(byte[] a, byte[] b)
|
||||
{
|
||||
if(a.Length != b.Length)
|
||||
{
|
||||
throw new ArgumentException("Array are not same Length");
|
||||
}
|
||||
|
||||
byte[] c = new byte[a.Length];
|
||||
|
||||
for(int i = 0; i < a.Length; i++)
|
||||
{
|
||||
c[i] = (byte)(a[i] ^ b[i]);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
@ -192,7 +266,7 @@ namespace NFC.Mifare_DESFire
|
||||
{
|
||||
byte[] id_byte = BitConverter.GetBytes(aid);
|
||||
|
||||
APDUCommand cmd = new APDUCommand(IsoCase.Case3Short)
|
||||
APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
|
||||
{
|
||||
CLA = 0x90,
|
||||
INS = (byte)APDUInstructions.SELECT_APPLICATION,
|
||||
@ -201,8 +275,7 @@ namespace NFC.Mifare_DESFire
|
||||
id_byte[0],
|
||||
id_byte[1],
|
||||
id_byte[2]
|
||||
},
|
||||
Le = 0x00
|
||||
}
|
||||
};
|
||||
|
||||
APDUResponse response = _Card.Transmit(cmd);
|
||||
@ -211,7 +284,76 @@ namespace NFC.Mifare_DESFire
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Expand Array to Block Size
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] expandToBlockSize(byte[] data, int bocksize)
|
||||
{
|
||||
int diff = data.Length % bocksize;
|
||||
if (diff == 0)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
byte[] expand = new byte[data.Length + diff];
|
||||
|
||||
data.CopyTo(expand, 0);
|
||||
|
||||
for(int i = expand.Length - 1; i > data.Length - 1; i--)
|
||||
{
|
||||
expand[i] = 0x00;
|
||||
}
|
||||
|
||||
return expand;
|
||||
}
|
||||
|
||||
public void ChangeKeyDES(byte key_no, byte[] key_new, byte[] key_current)
|
||||
{
|
||||
if(!CheckKey(key_new))
|
||||
{
|
||||
throw new ArgumentException("key_new is invalid");
|
||||
}
|
||||
|
||||
if (!CheckKey(key_current))
|
||||
{
|
||||
throw new ArgumentException("key_new is invalid");
|
||||
}
|
||||
|
||||
if(GetKeyTypeDES(key_new) != GetKeyTypeDES(key_current))
|
||||
{
|
||||
throw new ArgumentException("key_new and key_current are not same KeyType");
|
||||
}
|
||||
|
||||
byte[] keys_xor = xor(key_new, key_current);
|
||||
|
||||
keys_xor = concatenate(keys_xor, keys_xor);
|
||||
|
||||
CRC32 crc32 = new CRC32();
|
||||
byte[] crc = crc32.Calculate(new byte[] { (byte)APDUInstructions.CHANGE_KEY, key_no }, keys_xor);
|
||||
|
||||
byte[] key_xor_crc = concatenate(keys_xor, crc);
|
||||
|
||||
byte[] key_xor_crc_block = expandToBlockSize(key_xor_crc, 8);
|
||||
|
||||
|
||||
DES des = new DES();
|
||||
|
||||
byte[] key_xor_crc_block_enc = des.Encrypt(key_xor_crc_block, _SessionKey, _IV);
|
||||
|
||||
APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
|
||||
{
|
||||
CLA = 0x90,
|
||||
INS = (byte)APDUInstructions.CHANGE_KEY,
|
||||
Data = key_xor_crc_block_enc,
|
||||
Le = 0x00
|
||||
};
|
||||
|
||||
APDUResponse response = _Card.Transmit(cmd);
|
||||
|
||||
CheckAPDUResponse(response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -302,6 +444,58 @@ namespace NFC.Mifare_DESFire
|
||||
{
|
||||
throw new Exception("PICC Challenge is not correct answered.");
|
||||
}
|
||||
|
||||
_SessionKey = GenerateDESSesionKey(rndA, rndB);
|
||||
_IV = GenerateDefaultKey(8);
|
||||
}
|
||||
|
||||
private byte[] GenerateDESSesionKey(byte[] rndA, byte[] rndB)
|
||||
{
|
||||
byte[] sesssionkey = new byte[8];
|
||||
|
||||
for(int i = 0; i < sesssionkey.Length; i++)
|
||||
{
|
||||
if(i < 4)
|
||||
{
|
||||
sesssionkey[i] = rndA[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
sesssionkey[i] = rndB[i - 4];
|
||||
}
|
||||
}
|
||||
|
||||
// Set Key Verion of Key to 0x55 to LSB
|
||||
// TODO
|
||||
byte[] key_version = SetKeyVersion(sesssionkey, 0x55);
|
||||
|
||||
return concatenate(key_version, key_version);
|
||||
}
|
||||
|
||||
public byte[] SetKeyVersion(byte[] key, byte keyversion)
|
||||
{
|
||||
byte[] pow2 = new byte[]
|
||||
{
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
|
||||
};
|
||||
|
||||
byte[] new_key = new byte[key.Length];
|
||||
key.CopyTo(new_key, 0);
|
||||
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
if((keyversion & pow2[i]) > 0)
|
||||
{
|
||||
new_key[i] = (byte)(new_key[5] | 0x01);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_key[i] = (byte)(new_key[5] & 0x7F);
|
||||
}
|
||||
}
|
||||
|
||||
return new_key;
|
||||
}
|
||||
|
||||
public void ChangeApplicationMasterKey(byte[] aPP_MasterKey)
|
||||
@ -313,7 +507,7 @@ namespace NFC.Mifare_DESFire
|
||||
/// Delete Application by ID
|
||||
/// </summary>
|
||||
/// <param name="id">3 Byte ID</param>
|
||||
public APDUCommand DeleteApplication(UInt32 id)
|
||||
public void DeleteApplication(UInt32 id)
|
||||
{
|
||||
byte[] id_byte = BitConverter.GetBytes(id);
|
||||
|
||||
@ -330,7 +524,8 @@ namespace NFC.Mifare_DESFire
|
||||
Le = 0x00
|
||||
};
|
||||
|
||||
return cmd;
|
||||
APDUResponse response = _Card.Transmit(cmd);
|
||||
CheckAPDUResponse(response);
|
||||
}
|
||||
|
||||
public void ChangeApplicationKey(int v, byte[] aPP_Key_1)
|
||||
|
Reference in New Issue
Block a user