Added: Create STD File, ReadData, WriteData

This commit is contained in:
TheJoKlLa 2020-10-14 00:26:23 +02:00
parent 2c0db72f55
commit 2049e7eba3
32 changed files with 1867 additions and 1970 deletions

View File

@ -62,6 +62,5 @@ namespace Borepin.iOS.CNFC
// TODO: decide what to do // TODO: decide what to do
Console.WriteLine("reader session invalidated"); Console.WriteLine("reader session invalidated");
} }
} }
} }

View File

@ -2,26 +2,14 @@
namespace NFC.Crypto namespace NFC.Crypto
{ {
/// <summary>
/// CRC16 for DESFire Card
/// </summary>
public class CRC16 public class CRC16
{ {
public byte[] Calculate(byte[] data) public UInt16 Polynomial { get; } = 0x8408;
{
UInt16 crc16 = 0x6363;
crc16 = Calculate(data, crc16); public UInt16 InitValue { get; } = 0x6363;
return BitConverter.GetBytes(crc16);
}
public byte[] Calculate(byte[] cmd, byte[] data)
{
UInt16 crc16 = 0x6363;
crc16 = Calculate(cmd, crc16);
crc16 = Calculate(data, crc16);
return BitConverter.GetBytes(crc16);
}
public UInt16 Calculate(byte[] data, UInt16 crc16) public UInt16 Calculate(byte[] data, UInt16 crc16)
{ {
@ -34,11 +22,23 @@ namespace NFC.Crypto
crc16 >>= 1; crc16 >>= 1;
if (b_Bit) if (b_Bit)
{ {
crc16 ^= 0x8408; crc16 ^= Polynomial;
} }
} }
} }
return crc16; return crc16;
} }
public byte[] Calculate(params byte[][] data)
{
UInt16 crc16 = InitValue;
foreach(byte[] d in data)
{
crc16 = Calculate(d, crc16);
}
return BitConverter.GetBytes(crc16);
}
} }
} }

View File

@ -1,28 +1,15 @@
using System; using System;
using System.Linq;
namespace NFC.Crypto namespace NFC.Crypto
{ {
/// <summary>
/// CRC32 for DESFire Card
/// </summary>
public class CRC32 public class CRC32
{ {
public byte[] Calculate(byte[] data) public UInt32 Polynomial { get; } = 0xEDB88320;
{
UInt32 crc32 = 0xFFFFFFFF;
crc32 = Calculate(data, crc32); public UInt32 InitValue { get; } = 0xFFFFFFFF;
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) public UInt32 Calculate(byte[] data, UInt32 crc32)
{ {
@ -35,11 +22,23 @@ namespace NFC.Crypto
crc32 >>= 1; crc32 >>= 1;
if (b_Bit) if (b_Bit)
{ {
crc32 ^= 0xEDB88320; crc32 ^= Polynomial;
} }
} }
} }
return crc32; return crc32;
} }
public byte[] Calculate(params byte[][] data)
{
UInt32 crc32 = InitValue;
foreach(byte[] d in data)
{
crc32 = Calculate(d, crc32);
}
return BitConverter.GetBytes(crc32);
}
} }
} }

View File

@ -1,13 +1,16 @@
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Crypto namespace NFC.Crypto
{ {
public class AES public class AES : ICipher
{ {
public uint BlockSize { get; } = 16;
public uint KeySize { get; } = 16;
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{ {
AesEngine engine = new AesEngine(); AesEngine engine = new AesEngine();

49
NFC/Crypto/Cipher/TDES.cs Normal file
View File

@ -0,0 +1,49 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Crypto
{
public class TDES : ICipher
{
public uint BlockSize { get; } = 8;
// Two times the DES Key
public uint KeySize { get; } = 16;
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
DesEngine engine = new DesEdeEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
KeyParameter keyParam = new KeyParameter(key);
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv);
// Encrypt
cipher.Init(true, keyParamWithIV);
byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)];
int length = cipher.ProcessBytes(data, outputBytes, 0);
cipher.DoFinal(outputBytes, length);
return outputBytes;
}
public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
DesEngine engine = new DesEdeEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
KeyParameter keyParam = new KeyParameter(key);
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv);
// Decrypt
cipher.Init(false, keyParamWithIV);
byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)];
int length = cipher.ProcessBytes(data, outputBytes, 0);
cipher.DoFinal(outputBytes, length);
return outputBytes;
}
}
}

View File

@ -1,13 +1,16 @@
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Crypto namespace NFC.Crypto
{ {
public class TripleDES public class TDES_2K : ICipher
{ {
public uint BlockSize { get; } = 8;
public uint KeySize { get; } = 16;
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{ {
DesEngine engine = new DesEdeEngine(); DesEngine engine = new DesEdeEngine();

View File

@ -1,16 +1,19 @@
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Crypto namespace NFC.Crypto
{ {
public class DES public class TDES_3K : ICipher
{ {
public uint BlockSize { get; } = 8;
public uint KeySize { get; } = 24;
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{ {
DesEngine engine = new DesEngine(); DesEngine engine = new DesEdeEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
KeyParameter keyParam = new KeyParameter(key); KeyParameter keyParam = new KeyParameter(key);
@ -27,7 +30,7 @@ namespace NFC.Crypto
public byte[] Decrypt(byte[] data, byte[] key, byte[] iv) public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{ {
DesEngine engine = new DesEngine(); DesEngine engine = new DesEdeEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
KeyParameter keyParam = new KeyParameter(key); KeyParameter keyParam = new KeyParameter(key);

171
NFC/Crypto/CipherKey.cs Normal file
View File

@ -0,0 +1,171 @@
using System;
namespace NFC.Crypto
{
/// <summary>
/// Key for DESFire Card
/// </summary>
public class CipherKey
{
#region Constructors
/// <summary>
/// Creates Key from Array
/// </summary>
/// <param name="key">Key</param>
/// <param name="cipher">Cipher for Key</param>
/// <param name="keyVersion">Version of Key</param>
public CipherKey(byte[] key, CipherType cipher, byte keyVersion)
{
_Cipher = cipher;
if (cipher == CipherType.AES && keyVersion < 0x10)
{
throw new ArgumentOutOfRangeException("KeyVersion is to low for AES Key (Minimum = 0x10)");
}
_KeyVersion = keyVersion;
if (!CheckKey(key, cipher))
{
throw new ArgumentException("Key is not vaild for CipherType");
}
if (cipher == CipherType.TDES || cipher == CipherType.TDES_2K || cipher == CipherType.TDES_3K)
{
_Key = SetKeyVersion(key, keyVersion);
}
else
{
_Key = key;
}
}
/// <summary>
/// Generates Empty Key
/// </summary>
/// <param name="cipher">Cipher for Key</param>
/// <param name="keyVerion"></param>
public CipherKey(CipherType cipher)
{
_Cipher = cipher;
_Key = GenerateEmptyKey(cipher);
if (cipher == CipherType.AES)
{
_KeyVersion = 0x10;
}
else
{
_KeyVersion = 0x00;
}
}
#endregion
#region Properties
/// <summary>
/// Key as Array
/// </summary>
public byte[] _Key { get; private set; }
/// <summary>
/// CipherType of Key
/// </summary>
public CipherType _Cipher { get; private set; }
/// <summary>
/// KeyVersion of Key
/// For AES 0x10 is minimum
/// </summary>
public byte _KeyVersion { get; private set; }
#endregion
#region Methods
/// <summary>
/// Generate Empty Key for CipherType
/// </summary>
/// <param name="cipher">Type of Cipher</param>
public byte[] GenerateEmptyKey(CipherType cipher)
{
uint size = GetKeySize(cipher);
byte[] key = new byte[size];
for (int i = 0; i < size; i++)
{
key[i] = 0;
}
return key;
}
/// <summary>
/// Check Key Array
/// </summary>
/// <param name="key">Key</param>
/// <param name="cipher">Cipher Type of Key</param>
public bool CheckKey(byte[] key, CipherType cipher)
{
if (key.Length != GetKeySize(cipher))
{
return false;
}
else
{
return true;
}
}
/// <summary>
/// Get KeySize for CipherType
/// </summary>
/// <param name="cipher">Type of Cipher</param>
public uint GetKeySize(CipherType cipher)
{
switch (cipher)
{
case CipherType.TDES:
return 8;
case CipherType.TDES_2K:
return 16;
case CipherType.TDES_3K:
return 24;
case CipherType.AES:
return 16;
default:
throw new ArgumentOutOfRangeException("Unknown CipherType.");
}
}
/// <summary>
/// Set Key Version for DES/TDES Keys
/// KeyVersion is stored in the LSBits of the first 8 Bytes
/// Parity Bits are not used from DESFire Cars
/// </summary>
/// <param name="key"></param>
/// <param name="version"></param>
/// <returns></returns>
public byte[] SetKeyVersion(byte[] key, byte version)
{
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 ((version & pow2[i]) > 0)
{
new_key[i] = (byte)(new_key[5] | 0x01);
}
else
{
new_key[i] = (byte)(new_key[5] & 0x7F);
}
}
return new_key;
}
#endregion
}
}

25
NFC/Crypto/CipherType.cs Normal file
View File

@ -0,0 +1,25 @@
namespace NFC.Crypto
{
public enum CipherType
{
/// <summary>
/// DES / Triple DES
/// </summary>
TDES,
/// <summary>
/// Triple DES with 2 DES Keys
/// </summary>
TDES_2K,
/// <summary>
/// Triple DES with 3 DES Keys
/// </summary>
TDES_3K,
/// <summary>
/// AES
/// </summary>
AES
}
}

32
NFC/Crypto/ICipher.cs Normal file
View File

@ -0,0 +1,32 @@
namespace NFC.Crypto
{
public interface ICipher
{
/// <summary>
/// Size of Cipher Block in Byte
/// </summary>
public uint BlockSize { get; }
/// <summary>
/// Size of Key in Byte
/// </summary>
public uint KeySize { get; }
/// <summary>
/// Encrypt Data
/// </summary>
/// <param name="data">Data in BlockSize</param>
/// <param name="key">Key</param>
/// <param name="IV">Initialisation Vector</param>
/// <returns></returns>
public byte[] Encrypt(byte[] data, byte[] key, byte[] IV);
/// <summary>
/// Decrypt Data
/// </summary>
/// <param name="data">Data in BlockSize</param>
/// <param name="key">Key</param>
/// <param name="IV">Initialisation Vector</param>
public byte[] Decrypt(byte[] data, byte[] key, byte[] IV);
}
}

51
NFC/HexConverter.cs Normal file
View File

@ -0,0 +1,51 @@
using System;
namespace NFC
{
/// <summary>
/// Converts to and from Byte Array from and to String
/// </summary>
public static class HexConverter
{
/// <summary>
/// Converts byte[] to string with HEX Code
/// No 0x is created
/// </summary>
/// <param name="data">Data</param>
public static string ConvertToHexString(byte[] data)
{
return BitConverter.ToString(data).Replace("-", "").ToLower();
}
/// <summary>
/// Converts string with HEX Code to byte[]
/// No 0x is requiered
/// </summary>
/// <param name="data">Data</param>
public static byte[] ConvertFromHexString(string data)
{
if (data.Length % 2 == 1)
throw new Exception("Data Length is uneven.");
byte[] arr = new byte[data.Length >> 1];
for (int i = 0; i < data.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1])));
}
return arr;
}
private static int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
}
}

View File

@ -1,7 +1,7 @@
using PCSC; using PCSC;
using PCSC.Iso7816; using PCSC.Iso7816;
using System; using System;
using System.Collections.Generic; using System.Linq;
namespace NFC.ISO7816_4 namespace NFC.ISO7816_4
{ {
@ -21,7 +21,8 @@ namespace NFC.ISO7816_4
INS == command.INS && INS == command.INS &&
P1 == command.P1 && P1 == command.P1 &&
P2 == command.P2 && P2 == command.P2 &&
EqualityComparer<byte[]>.Default.Equals(Data, command.Data); Data.SequenceEqual(command.Data) &&
Le == command.Le;
} }
public override int GetHashCode() public override int GetHashCode()
@ -43,5 +44,40 @@ namespace NFC.ISO7816_4
hash.Add(IsValid); hash.Add(IsValid);
return hash.ToHashCode(); return hash.ToHashCode();
} }
public static bool operator ==(APDUCommand obj1, APDUCommand obj2)
{
return obj1.Equals(obj2);
}
public static bool operator !=(APDUCommand obj1, APDUCommand obj2)
{
return !(obj1.Equals(obj2));
}
public override string ToString()
{
string pattern_case1 = "(CASE: 1) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x}";
string pattern_case2 = "(CASE: 2) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LE: 0x{4:x} |";
string pattern_case3 = "(CASE: 3) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LC: 0x{4:x} | Data: {5:x}";
string pattern_case4 = "(CASE: 4) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LC: 0x{4:x} | Data: {5:x} | LE: 0x{6:x} |";
switch (Case)
{
case IsoCase.Case1:
return string.Format(pattern_case1, CLA, INS, P1, P2);
case IsoCase.Case2Short:
case IsoCase.Case2Extended:
return string.Format(pattern_case2, CLA, INS, P1, P2, Le);
case IsoCase.Case3Short:
case IsoCase.Case3Extended:
return string.Format(pattern_case3, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " "));
case IsoCase.Case4Short:
case IsoCase.Case4Extended:
return string.Format(pattern_case4, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " "), Le);
default:
throw new Exception("Unknown IsoCase");
}
}
} }
} }

View File

@ -28,7 +28,7 @@
CREATE_CYCLIC_RECORD_FILE = 0xC0, CREATE_CYCLIC_RECORD_FILE = 0xC0,
DELETE_FILE = 0xDF, DELETE_FILE = 0xDF,
GET_ISO_FILE_IDS = 0x61, GET_ISO_FILE_IDS = 0x61,
READ_DATA = 0x8D, READ_DATA = 0xBD,
WRITE_DATA = 0x3D, WRITE_DATA = 0x3D,
GET_VALUE = 0x6C, GET_VALUE = 0x6C,
CREDIT = 0x0C, CREDIT = 0x0C,

View File

@ -0,0 +1,106 @@
using NFC.Crypto;
using System;
namespace NFC.NXP_MIFARE_DESFire
{
public class CMAC
{
#region Contructors
public CMAC(CipherType cipher)
{
switch(cipher)
{
case(CipherType.TDES):
_Cipher = new TDES();
break;
case(CipherType.TDES_2K):
_Cipher = new TDES_2K();
break;
case(CipherType.TDES_3K):
_Cipher = new TDES_3K();
break;
case (CipherType.AES):
_Cipher = new AES();
break;
default:
throw new ArgumentException("Unkown Cipher Type.");
}
}
public CMAC(ICipher cipher)
{
_Cipher = cipher ?? throw new ArgumentNullException();
}
#endregion
#region Properties
private ICipher _Cipher;
#endregion
#region Methods
/// <summary>
/// Generate Key with all Zeros, in KeySize
/// </summary>
public byte[] GenerateEmpytKey()
{
byte[] key = new byte[_Cipher.KeySize];
for (int i = 0; i < _Cipher.KeySize; i++)
{
key[i] = 0;
}
return key;
}
/// <summary>
/// Generate IV with all Zeros, in KeySize
/// </summary>
public byte[] GenerateEmpytIV()
{
byte[] key = new byte[_Cipher.BlockSize];
for (int i = 0; i < _Cipher.BlockSize; i++)
{
key[i] = 0;
}
return key;
}
/// <summary>
/// Encrypt Data
/// </summary>
public byte[] Encrypt(byte[] data)
{
throw new NotImplementedException();
}
/// <summary>
/// Decrypt Data
/// </summary>
public byte[] Decrypt(byte[] data)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <returns>Two Keys</returns>
public byte[][] GenerateSubKey()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public byte[] Digest(byte[] data)
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@ -1,6 +1,6 @@
namespace NFC.Mifare_DESFire.Enums namespace NFC.Mifare_DESFire.Enums
{ {
public enum AccessRights : byte public enum FileAccessRights : byte
{ {
FREE = 0x0E, FREE = 0x0E,
NEVER = 0x0F NEVER = 0x0F

View File

@ -1,4 +1,4 @@
namespace NFC.Mifare_DESFire namespace NFC.Mifare_DESFire.Enums
{ {
enum FileTypes : byte enum FileTypes : byte
{ {

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Current authentication status does not allow there- quested command.
/// 0x91AE
/// </summary>
public class AuthenticationMissingException : Exception
{
public AuthenticationMissingException()
{
}
public AuthenticationMissingException(string message) : base(message)
{
}
public AuthenticationMissingException(string message, Exception inner) : base(message, inner)
{
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,844 +0,0 @@
using log4net.Repository.Hierarchy;
using NFC.Crypto;
using NFC.ISO7816_4;
using NFC.Mifare_DESFire.Enums;
using NFC.NXP_MIFARE_DESFire.Exceptions;
using PCSC.Iso7816;
using System;
using System.Linq;
namespace NFC.Mifare_DESFire
{
public class MIFARE_DESFire_V2
{
// Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg
#region Log
private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion
#region Contructors
/// <summary>
/// Construct MIFRARE_DESFire Object with ICard Interface
/// </summary>
/// <param name="card">Implementation of ICard, only transmit is used</param>
public MIFARE_DESFire_V2(ICard card)
{
_Card = card;
}
#endregion
#region Properties
/// <summary>
/// ICard Implementation used to transmit APDUCommands and recive APDUResponses
/// </summary>
private ICard _Card;
/// <summary>
/// SessionKey, is set after Successfull Authentication
/// </summary>
public byte[] _SessionKey;
/// <summary>
/// Initialation Vector for CBC Encryption
/// Is 0 bytes after Successfull Authentication
/// </summary>
public byte[] _IV;
#endregion
#region Methods
#region Helper Methods
/// <summary>
/// Generate Byte Array filled with 0
/// </summary>
/// <param name="size">Size of Array</param>
public byte[] GenerateEmptyKey(uint size)
{
byte[] key = new byte[size];
for (int i = 0; i < size; i++)
{
key[i] = 0;
}
return key;
}
/// <summary>
/// Converts byte[] to string with HEX Code
/// No 0x is created
/// </summary>
/// <param name="data">Data</param>
public string ConvertToHexString(byte[] data)
{
return BitConverter.ToString(data).Replace("-", "").ToLower();
}
/// <summary>
/// Converts string with HEX Code to byte[]
/// No 0x is requiered
/// </summary>
/// <param name="data">Data</param>
public byte[] ConvertFromHexString(string data)
{
if (data.Length % 2 == 1)
throw new Exception("Data Length is uneven.");
byte[] arr = new byte[data.Length >> 1];
for (int i = 0; i < data.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1])));
}
return arr;
}
private int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
/// <summary>
/// Check APDU Response for DESFire Error Codes
/// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf
/// Section: 11.3
/// </summary>
public void CheckAPDUResponse(APDUResponse response)
{
if (response == null)
{
throw new ArgumentNullException("Response cannot be null.");
}
if (response.SW1 == 0x91)
{
switch (response.SW2)
{
case 0x00: // OPERATION_OK
return;
case 0x0C: // NO_CHANGES
return;
case 0x1C: // ILLEGAL_COMMAND_CODE
throw new IllegalCommandCodeException();
case 0x1E: // INTEGRITY_ERROR
throw new IntegrityErrorException();
case 0x40: // NO_SUCH_KEY
throw new NoSuchKeyException();
case 0x7E: // LENGTH_ERROR
throw new LengthErrorException();
case 0x9D: // PERMISSION_DENIED
throw new PermissionDeniedException();
case 0x9E: // PARAMETER_ERROR
throw new ParameterErrorException();
case 0xAD: // AUTHENTICATION_DELAY
throw new AuthenticationDelayException();
case 0xAE: // AUTHENTICATION_ERROR
throw new AuthenticationErrorException();
case 0xAF: // ADDITIONAL_FRAME
return;
case 0xBE: // BOUNDARY_ERROR
throw new BoundaryErrorException();
case 0xCA: // COMMAND_ABORTED
throw new CommandAbortedException();
case 0xDE: // DUPLICATE_ERROR
throw new DuplicateErrorException();
case 0xF0: // FILE_NOT_FOUND
throw new FileNotFoundException();
default:
break;
}
}
throw new Exception(string.Format("Unknown Response Code: 0x{0}.", BitConverter.ToString(new byte[] { response.SW1, response.SW2 }).Replace("-", string.Empty)));
}
#endregion
#region Crypto Operation
/// <summary>
/// Return a copy of the last Block of data
/// </summary>
/// <param name="data">Data compatible to blocksize</param>
/// <param name="blocksize">in byte</param>
public byte[] ExtractLastBlock(byte[] data, uint blocksize)
{
if (data == null)
{
throw new ArgumentNullException("Data cannot be null.");
}
if (data.Length % blocksize != 0)
{
throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}.", data.Length, blocksize));
}
byte[] lastblock = new byte[blocksize];
for (int i = 0; i < blocksize; i++)
{
lastblock[i] = data[data.Length - blocksize + i];
}
return lastblock;
}
/// <summary>
/// Rotates Array to the left
/// </summary>
/// <param name="data">Data</param>
/// <returns>Copy of data</returns>
public byte[] RotateLeft(byte[] data)
{
if (data == null)
{
throw new ArgumentNullException("Data cannot be null.");
}
byte[] rotate = new byte[data.Length];
data.CopyTo(rotate, 0);
byte tmp = rotate[0];
for (var i = 0; i < rotate.Length - 1; i++)
{
rotate[i] = rotate[i + 1];
}
rotate[rotate.Length - 1] = tmp;
return rotate;
}
/// <summary>
/// Rotates Array to the right
/// </summary>
/// <param name="data">Data</param>
/// <returns>Copy of data</returns>
public byte[] RotateRight(byte[] data)
{
if (data == null)
{
throw new ArgumentNullException("Data cannot be null.");
}
byte[] rotate = new byte[data.Length];
data.CopyTo(rotate, 0);
byte tmp = rotate[rotate.Length - 1];
for (var i = rotate.Length - 1; i > 0; i--)
{
rotate[i] = rotate[i - 1];
}
rotate[0] = tmp;
return rotate;
}
/// <summary>
/// Concatenates two Arrays, Array A start at index 0
/// </summary>
/// <param name="a">Array A</param>
/// <param name="b">Array B</param>
/// <returns>Copy of Data (a.Size + b.Size)</returns>
public byte[] Concatenate(byte[] a, byte[] b)
{
if (a == null)
{
throw new ArgumentNullException("Array A cannot be null.");
}
if (b == null)
{
throw new ArgumentNullException("Array B cannot be null.");
}
byte[] c = new byte[a.Length + b.Length];
a.CopyTo(c, 0);
b.CopyTo(c, a.Length);
return c;
}
/// <summary>
/// Boolean Operation XOR on all Bytes
/// </summary>
/// <param name="a">Array A</param>
/// <param name="b">Array B</param>
/// <returns>Copy of Data</returns>
public byte[] XOR(byte[] a, byte[] b)
{
if (a == null)
{
throw new ArgumentNullException("Array A cannot be null.");
}
if (b == null)
{
throw new ArgumentNullException("Array B cannot be null.");
}
if (a.Length != b.Length)
{
throw new ArgumentException(string.Format("Arrays are not same Length(Length A:{0}, Lenght B:{1})", a.Length, b.Length));
}
byte[] c = new byte[a.Length];
for(int i = 0; i < a.Length; i++)
{
c[i] = (byte)(a[i] ^ b[i]);
}
return c;
}
/// <summary>
/// Generates SessionKey for DES Authentification
/// </summary>
/// <returns>16Byte SessionKey</returns>
public byte[] GenerateSesionKey_DES(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];
}
}
// DES SessionKey is a double DES Key
return Concatenate(sesssionkey, sesssionkey);
}
/// <summary>
/// Generates SessionKey for AES Authentification
/// </summary>
/// <returns>16Byte SessionKey</returns>
public byte[] GenerateSesionKey_AES(byte[] rndA, byte[] rndB)
{
byte[] sesssionkey = new byte[16];
for (int i = 0; i < sesssionkey.Length; i++)
{
if (i < 4)
{
sesssionkey[i] = rndA[i];
}
else if(i >= 4 && i < 8)
{
sesssionkey[i] = rndB[i - 4];
}
else if (i >= 8 && i < 12)
{
sesssionkey[i] = rndA[i + 4];
}
else
{
sesssionkey[i] = rndB[i];
}
}
return sesssionkey;
}
/// <summary>
/// Set KeyVersion in DES Key
/// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key
/// </summary>
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;
}
/// <summary>
/// Expand Array to Block Size, fill with 0x00
/// </summary>
/// <param name="data"></param>
public byte[] ExpandToBlockSize(byte[] data, uint bocksize)
{
int diff = data.Length % (int)bocksize;
if (diff == 0)
{
return data;
}
byte[] expand = new byte[data.Length + bocksize - diff];
data.CopyTo(expand, 0);
for (int i = expand.Length - 1; i > data.Length - 1; i--)
{
expand[i] = 0x00;
}
return expand;
}
#endregion
#region DESFire Commands
/// <summary>
/// Authenticate to PICC, with ISO Authenticate
/// </summary>
/// <param name="key_id">0x01 - 0x0D</param>
/// <param name="key"></param>
/// <param name="rndA">!!! WARNING For Testing only !!!</param>
/// <exception cref="AuthenticationDelayException">Retry after short Time</exception>
public void AuthenticateISO_DES(byte key_id, byte[] key, byte[] rndA = null)
{
_Log.Debug("Start AuthenticateISO_DES");
// Sepearte InitialisationVector for Authentication
byte[] iv = new byte[8];
APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0x1A,
Data = new byte[]
{
key_id
}
};
_Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
APDUResponse response = _Card.Transmit(cmd_challange_request);
_Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
byte[] rndB_enc = response.Body;
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
DES des = new DES();
byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8));
_Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
rndB.CopyTo(iv, 0);
byte[] rndB_rl = RotateLeft(rndB);
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
if(rndA == null)
{
Random rnd = new Random();
rndA = new byte[8];
rnd.NextBytes(rndA);
}
_Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
byte[] rndAB = Concatenate(rndA, rndB_rl);
_Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc);
_Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
iv = ExtractLastBlock(rndAB_enc, 8);
APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xAF,
Data = rndAB_enc
};
_Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
response = _Card.Transmit(cmd_challange_response);
_Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
CheckAPDUResponse(response);
byte[] encryptedRndAFromCard = response.Body;
_Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv);
_Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
_Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
if (!rndA.SequenceEqual(rndAFromCard))
{
throw new Exception("Authentication failed, PICC Challenge is not corret");
}
_SessionKey = GenerateSesionKey_DES(rndA, rndB);
_Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
_IV = GenerateEmptyKey(8);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
_Log.Debug("End AuthenticateISO_DES");
}
/// <summary>
/// Format PICC
/// </summary>
public void Format()
{
_Log.Debug("Start Format");
APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short)
{
CLA = 0x90,
INS = 0xFC,
};
_Log.DebugFormat("APDU_CMD(cmd_format): {0}", ConvertToHexString(cmd_format.ToArray()));
APDUResponse response = _Card.Transmit(cmd_format);
_Log.DebugFormat("APDU_RES(cmd_format): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End Format");
}
/// <summary>
/// Create Application for ID
/// </summary>
/// <param name="aid">3 Byte ID</param>
public void CreateApplication(UInt32 aid, byte keysetting1, byte keysetting2)
{
_Log.Debug("Start CreateApplication");
byte[] id_byte = BitConverter.GetBytes(aid);
_Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xCA,
Data = new byte[]
{
id_byte[0],
id_byte[1],
id_byte[2],
keysetting1,
keysetting2
}
};
_Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray()));
APDUResponse response = _Card.Transmit(cmd_CreateApplication);
_Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End CreateApplication");
}
/// <summary>
/// Select Application by AID
/// </summary>
/// <param name="aid">3 Byte AID</param>
public void SelectApplication(UInt32 aid)
{
_Log.Debug("Start SelectApplication");
byte[] id_byte = BitConverter.GetBytes(aid);
_Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)APDUInstructions.SELECT_APPLICATION,
Data = new byte[]
{
id_byte[0],
id_byte[1],
id_byte[2]
}
};
_Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray()));
APDUResponse response = _Card.Transmit(cmd_SelectApplication);
_Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End SelectApplication");
}
/// <summary>
/// Authenticate to PICC, with ISO Authenticate
/// </summary>
/// <param name="key_id">0x01 - 0x0D</param>
/// <param name="key"></param>
/// <param name="rndA">!!! WARNING For Testing only !!!</param>
/// <exception cref="AuthenticationDelayException">Retry after short Time</exception>
public void AuthenticateISO_AES(byte key_id, byte[] key, byte[] rndA = null)
{
_Log.Debug("Start AuthenticateISO_AES");
// Sepearte InitialisationVector for Authentication
byte[] iv = new byte[16];
APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xAA,
Data = new byte[]
{
key_id
}
};
_Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
APDUResponse response = _Card.Transmit(cmd_challange_request);
_Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
byte[] rndB_enc = response.Body;
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
AES aes = new AES();
byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16));
_Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
rndB.CopyTo(iv, 0);
byte[] rndB_rl = RotateLeft(rndB);
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
if (rndA == null)
{
Random rnd = new Random();
rndA = new byte[16];
rnd.NextBytes(rndA);
}
_Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
byte[] rndAB = Concatenate(rndA, rndB_rl);
_Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc);
_Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
iv = ExtractLastBlock(rndAB_enc, 16);
APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xAF,
Data = rndAB_enc
};
_Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
response = _Card.Transmit(cmd_challange_response);
_Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
CheckAPDUResponse(response);
byte[] encryptedRndAFromCard = response.Body;
_Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv);
_Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
_Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
if (!rndA.SequenceEqual(rndAFromCard))
{
throw new Exception("Authentication failed, PICC Challenge is not corret");
}
_SessionKey = GenerateSesionKey_AES(rndA, rndB);
_Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
_IV = GenerateEmptyKey(16);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
_Log.Debug("End AuthenticateISO_DES");
}
/// <summary>
/// Change Same AES key as Authenticated
/// </summary>
/// <param name="key_id"></param>
/// <param name="new_key"></param>
/// <param name="key_version"></param>
public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version)
{
_Log.Debug("Start ChangeKey_AES");
byte[] header = new byte[]
{
0xC4, key_id
};
_Log.DebugFormat("header: {0}", ConvertToHexString(header));
// AES Key Version is Append to Key
byte[] key_and_version = Concatenate(new_key, new byte[] { key_version });
byte[] command = Concatenate(header, key_and_version);
_Log.DebugFormat("command: {0}", ConvertToHexString(command));
CRC32 crc32 = new CRC32();
byte[] crc = crc32.Calculate(command);
_Log.DebugFormat("crc: {0}", ConvertToHexString(crc));
byte[] cryptogram = Concatenate(key_and_version, crc);
_Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
_Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
AES aes = new AES();
byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
_Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
_IV = ExtractLastBlock(cryptogram_enc, 16);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
_Log.DebugFormat("data: {0}", ConvertToHexString(data));
APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xC4,
Data = data
};
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ChangeKey);
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End ChangeKey_AES");
}
/// <summary>
/// Change other AES key as Authenticated
/// </summary>
/// <param name="key_id"></param>
/// <param name="new_key"></param>
/// <param name="key_version"></param>
public void ChangeOtherKey_AES(byte key_id, byte[] new_key, byte[] old_key, byte key_version)
{
_Log.Debug("Start ChangeOtherKey_AES");
byte[] header = new byte[]
{
0xC4, key_id
};
_Log.DebugFormat("header: {0}", ConvertToHexString(header));
byte[] key_xor = XOR(new_key, old_key);
// AES Key Version is Append to Key
byte[] key_and_version = Concatenate(key_xor, new byte[] { key_version });
byte[] command = Concatenate(header, key_and_version);
_Log.DebugFormat("command: {0}", ConvertToHexString(command));
CRC32 crc32 = new CRC32();
byte[] crc_cmd = crc32.Calculate(command);
_Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd));
byte[] crc_key = crc32.Calculate(new_key);
_Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key));
byte[] cryptogram = Concatenate(key_and_version, crc_cmd);
cryptogram = Concatenate(cryptogram, crc_key);
_Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
_Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
AES aes = new AES();
byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
_Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
_IV = ExtractLastBlock(cryptogram_enc, 16);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
_Log.DebugFormat("data: {0}", ConvertToHexString(data));
APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xC4,
Data = data
};
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ChangeKey);
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End ChangeOtherKey_AES");
}
public void CreateFile_STD()
#endregion
#region Configuration Generator
/// <summary>
/// Genearte KeySetting1 for Application Settings or PICC Setting
/// </summary>
public byte GenerateKeySetting1(ChangeApplicationKey changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey)
{
return (byte)(((byte)changeKey << 4) | (byte)changeMasterKeySettings | (byte)createDeleteFile | (byte)fileDirectoryAccess | (byte)changeMasterKey);
}
/// <summary>
/// Genearte KeySetting1 for Application Settings or PICC Setting
/// </summary>
/// <param name="changeKey">ID of Key for changing Application Keys</param>
/// <returns></returns>
public byte GenerateKeySetting1(byte changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey)
{
if (changeKey < 0x01 || changeKey >= 0x0E)
{
throw new ArgumentOutOfRangeException();
}
return GenerateKeySetting1(changeKey, changeMasterKeySettings, createDeleteFile, fileDirectoryAccess, changeMasterKey);
}
/// <summary>
/// Genearte KeySetting2 for Application Creation
/// </summary>
/// <param name="numberOfKeys">Number of keys that can be stored within the application (0x01-0x0D)</param>
/// <returns></returns>
public byte GenerateKeySetting2(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys)
{
if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D)
{
throw new ArgumentOutOfRangeException();
}
return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys);
}
#endregion
#endregion
}
}

View File

@ -1,211 +0,0 @@
using NFC;
using NFC.Crypto;
using NFC.ISO7816_4;
using NFC.Mifare_DESFire;
using NSubstitute;
using NUnit.Framework;
using PCSC.Iso7816;
using System;
using System.Collections.Generic;
using System.Text;
namespace NFC_Test
{
public class AuthCrypto_Test
{
public byte[] GenerateDefaultKey(int size)
{
List<byte> key = new List<byte>();
for (int i = 0; i < size; i++)
{
key.Add(0);
}
return key.ToArray();
}
[Test]
// https://www.linkedin.com/pulse/mifare-desfire-introduction-david-coelho
public void AuthExample()
{
DES des = new DES();
byte[] challenge = new byte[]
{
0x93 ,0x9d ,0x2c ,0x2e ,0xa1 ,0x65 ,0x75 ,0xd5
};
byte[] key = GenerateDefaultKey(8);
byte[] iv = GenerateDefaultKey(8);
byte[] rndA = new byte[]
{
0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07
};
byte[] rndB = des.Decrypt(challenge, key, iv);
byte[] rndB_expected = new byte[]
{
0xea ,0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67
};
Assert.AreEqual(rndB_expected, rndB);
}
[Test]
public void concatenate()
{
MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(null);
byte[] rndA = new byte[]
{
0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07
};
byte[] rndB = new byte[]
{
0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea
};
byte[] rndA_rndB_expected = new byte[]
{
0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07, 0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea
};
byte[] rndA_rndB = mifareDESFire.concatenate(rndA, rndB);
Assert.AreEqual(rndA_rndB_expected, rndA_rndB);
}
[Test]
public void Auth()
{
APDUCommand cmd_getchallange = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)0x1A,
Data = new byte[]
{
0x00
}
};
APDUCommand cmd_answerchallange = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)0xAF,
Data = new byte[]
{
0x69, 0x17, 0x8b, 0x93, 0x8c, 0x03, 0xed, 0xf1, 0x86, 0xd3, 0x05, 0x6b, 0xed, 0xc8, 0xd6, 0xcf
}
};
APDUResponse response = new APDUResponse()
{
Body = new byte[]
{
0xB8, 0x90, 0x04, 0x7F, 0x2D, 0xC8, 0xD6, 0x8B
}
};
APDUResponse response2 = new APDUResponse()
{
Body = new byte[]
{
0x04, 0x79, 0xed, 0x6c, 0x4f, 0x74, 0xda, 0x4a
}
};
ICard card = Substitute.For<ICard>();
card.Transmit(cmd_getchallange).ReturnsForAnyArgs(response);
card.Transmit(cmd_answerchallange).Returns(response2);
MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
mifareDESFire.AuthenticateDES(0x00, mifareDESFire.GenerateDefaultKey(16));
}
[Test]
public void ChangeKey()
{
ICard card = Substitute.For<ICard>();
MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
mifareDESFire._SessionKey = new byte[]
{
0xDC, 0xB0, 0x96, 0xC2, 0xA4, 0x0E, 0x78, 0xE0, 0xA0, 0xE4, 0x7A, 0x96, 0xF4, 0x2E, 0x62, 0xAE
};
mifareDESFire._IV = new byte[]
{
0x33, 0x45 , 0xAA , 0x95 , 0xF2 , 0xD9 , 0x56 , 0xCF
};
mifareDESFire.ChangeKeyDES(0x00, GenerateDefaultKey(16), GenerateDefaultKey(16));
}
[Test]
public void CRC()
{
byte[] data = StringToByteArrayFastest("c40045eeb8338ae8f49a032e85bb1114353010");
CRC32 crc32 = new CRC32();
byte[] crc = crc32.Calculate(data);
MIFARE_DESFire dESFire = new MIFARE_DESFire(null);
Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data));
Console.WriteLine("crc: {0}", dESFire.ConvertToHexString(crc));
byte[] data_crc = dESFire.concatenate(data, crc);
Console.WriteLine("data_crc: {0}", dESFire.ConvertToHexString(data_crc));
}
public static byte[] StringToByteArrayFastest(string hex)
{
if (hex.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[hex.Length >> 1];
for (int i = 0; i < hex.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
}
return arr;
}
public static int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
[Test]
public void AES()
{
byte[] data = StringToByteArrayFastest("45eeb8338ae8f49a032e85bb111435301095c3894b0000000000000000000000");
byte[] key = StringToByteArrayFastest("d99aca2b5b4de3a949fa2cf12b0eb673");
byte[] iv = StringToByteArrayFastest("00000000000000000000000000000000");
MIFARE_DESFire dESFire = new MIFARE_DESFire(null);
Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data));
Console.WriteLine("key: {0}", dESFire.ConvertToHexString(key));
Console.WriteLine("iv: {0}", dESFire.ConvertToHexString(iv));
AES aes = new AES();
byte[] data_enc = aes.Encrypt(data, key, iv);
Console.WriteLine("data_enc: {0}", dESFire.ConvertToHexString(data_enc));
}
}
}

View File

@ -2,7 +2,7 @@
using NFC.Mifare_DESFire; using NFC.Mifare_DESFire;
using NUnit.Framework; using NUnit.Framework;
namespace NFC_Test namespace NFC_Test.Crypto
{ {
[TestFixture] [TestFixture]
public class AES_Test public class AES_Test
@ -10,7 +10,7 @@ namespace NFC_Test
[Test] [Test]
public void Encrypt() public void Encrypt()
{ {
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12104a3b07e8eb77a7ac00000000000000"); byte[] data = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12104a3b07e8eb77a7ac00000000000000");
byte[] key = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); byte[] key = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b");

View File

@ -0,0 +1,23 @@
using NFC;
using NFC.Crypto;
using NUnit.Framework;
namespace NFC_Test.Crypto
{
[TestFixture]
public class CRC16_Test
{
[Test]
[Ignore("Unknown Expected Data")]
public void Caluclate()
{
byte[] data = HexConverter.ConvertFromHexString("");
byte[] crc_expected = HexConverter.ConvertFromHexString("");
CRC16 crc16 = new CRC16();
byte[] crc = crc16.Calculate(data);
Assert.AreEqual(crc_expected, crc);
}
}
}

View File

@ -0,0 +1,22 @@
using NFC;
using NFC.Crypto;
using NUnit.Framework;
namespace NFC_Test.Crypto
{
[TestFixture]
public class CRC32_Test
{
[Test]
public void Caluclate()
{
byte[] data = HexConverter.ConvertFromHexString("c40045eeb8338ae8f49a032e85bb1114353010");
byte[] crc_expected = HexConverter.ConvertFromHexString("95c3894b");
CRC32 crc32 = new CRC32();
byte[] crc = crc32.Calculate(data);
Assert.AreEqual(crc_expected, crc);
}
}
}

View File

@ -0,0 +1,61 @@
using NFC.Crypto;
using NFC.Mifare_DESFire;
using NUnit.Framework;
namespace NFC_Test.Crypto
{
[TestFixture]
public class TDES_Test
{
[Test]
[Ignore("Unknown Expected Data")]
public void Encrypt_TDES()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.ConvertFromHexString("");
byte[] key = desfire.ConvertFromHexString("");
byte[] iv = desfire.ConvertFromHexString("0000000000000000");
TDES des = new TDES();
byte[] data_enc = des.Encrypt(data, key, iv);
byte[] data_enc_expected = desfire.ConvertFromHexString("");
Assert.AreEqual(data_enc_expected, data_enc);
}
[Test]
[Ignore("Unknown Expected Data")]
public void Encrypt_TDES_2K()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.ConvertFromHexString("");
byte[] key = desfire.ConvertFromHexString("");
byte[] iv = desfire.ConvertFromHexString("0000000000000000");
TDES_2K des = new TDES_2K();
byte[] data_enc = des.Encrypt(data, key, iv);
byte[] data_enc_expected = desfire.ConvertFromHexString("");
Assert.AreEqual(data_enc_expected, data_enc);
}
[Test]
[Ignore("Unknown Expected Data")]
public void Encrypt_TDES_3K()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.ConvertFromHexString("");
byte[] key = desfire.ConvertFromHexString("");
byte[] iv = desfire.ConvertFromHexString("0000000000000000");
TDES_3K des = new TDES_3K();
byte[] data_enc = des.Encrypt(data, key, iv);
byte[] data_enc_expected = desfire.ConvertFromHexString("");
Assert.AreEqual(data_enc_expected, data_enc);
}
}
}

View File

@ -0,0 +1,119 @@
using System;
using NFC.ISO7816_4;
using NUnit.Framework;
using PCSC.Iso7816;
namespace NFC_Test.ISO7816_4
{
[TestFixture]
public class APDUCommand_Test
{
[Test]
public void Compare()
{
APDUCommand command1 = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xAA,
Data = new byte[]
{
0x01, 0x02, 0x03
}
};
APDUCommand command2 = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xAA,
Data = new byte[]
{
0x01, 0x02, 0x03
}
};
Assert.IsTrue(command1 == command2);
}
[Test]
public void Compare_Diff()
{
APDUCommand command1 = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xAA,
Data = new byte[]
{
0x01, 0x02, 0x03
}
};
APDUCommand command2 = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0x1A,
Data = new byte[]
{
0x01, 0x02, 0x03
}
};
Assert.IsFalse(command1 == command2);
}
[Test]
public void ToString_Case1()
{
APDUCommand command = new APDUCommand(IsoCase.Case1)
{
CLA = 0x90,
INS = 0x1A
};
Console.WriteLine(command.ToString());
}
[Test]
public void ToString_Case2()
{
APDUCommand command = new APDUCommand(IsoCase.Case2Short)
{
CLA = 0x90,
INS = 0x1A
};
Console.WriteLine(command.ToString());
}
[Test]
public void ToString_Case3()
{
APDUCommand command = new APDUCommand(IsoCase.Case3Short)
{
CLA = 0x90,
INS = 0x1A,
Data = new byte[]
{
0x01, 0x02, 0x03
}
};
Console.WriteLine(command.ToString());
}
[Test]
public void ToString_Case4()
{
APDUCommand command = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0x1A,
Data = new byte[]
{
0x01, 0x02, 0x03
}
};
Console.WriteLine(command.ToString());
}
}
}

View File

@ -1,34 +0,0 @@
using NFC;
using NFC.Mifare_DESFire;
using NFC.Mifare_DESFire.Enums;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Text;
namespace NFC_Test
{
[TestFixture]
public class MifareDESFire_Commands
{
private MIFARE_DESFire _MifareDESFire;
[SetUp]
public void SetUp()
{
//_MifareDESFire = new MifareDESFire();
}
[Test]
public void GetApplicationIDs()
{
}
[Test]
public void GenerateKeySetting1()
{
Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE));
}
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>

View File

@ -3,17 +3,13 @@ using NFC.ISO7816_4;
using NFC.Mifare_DESFire; using NFC.Mifare_DESFire;
using NFC.NXP_MIFARE_DESFire.Exceptions; using NFC.NXP_MIFARE_DESFire.Exceptions;
using NSubstitute; using NSubstitute;
using NSubstitute.Core;
using NUnit.Framework; using NUnit.Framework;
using PCSC.Iso7816;
using System; using System;
using System.Collections.Generic;
using System.Net;
namespace NFC_Test namespace NFC_Test.NXP_MIFARE_DESFire
{ {
[TestFixture] [TestFixture]
public class MIFARE_DESFire_V2_Test public class MIFARE_DESFire_Test
{ {
#region Helper Methods #region Helper Methods
[Test] [Test]
@ -21,7 +17,7 @@ namespace NFC_Test
{ {
uint i = 16; uint i = 16;
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.GenerateEmptyKey(i); byte[] data = desfire.GenerateEmptyKey(i);
@ -37,7 +33,7 @@ namespace NFC_Test
[Test] [Test]
public void CheckAPDUResponse__NULL() public void CheckAPDUResponse__NULL()
{ {
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>( Assert.Throws<ArgumentNullException>(
delegate delegate
{ {
@ -54,7 +50,7 @@ namespace NFC_Test
SW2 = 0x00 SW2 = 0x00
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<Exception>( Assert.Throws<Exception>(
delegate delegate
{ {
@ -71,7 +67,7 @@ namespace NFC_Test
SW2 = 0x00 SW2 = 0x00
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response); desfire.CheckAPDUResponse(response);
} }
@ -85,7 +81,7 @@ namespace NFC_Test
SW2 = 0x0C SW2 = 0x0C
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response); desfire.CheckAPDUResponse(response);
} }
@ -98,7 +94,7 @@ namespace NFC_Test
SW2 = 0x1C SW2 = 0x1C
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<IllegalCommandCodeException>( Assert.Throws<IllegalCommandCodeException>(
delegate delegate
@ -116,7 +112,7 @@ namespace NFC_Test
SW2 = 0x1E SW2 = 0x1E
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<IntegrityErrorException>( Assert.Throws<IntegrityErrorException>(
delegate delegate
@ -134,7 +130,7 @@ namespace NFC_Test
SW2 = 0x40 SW2 = 0x40
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<NoSuchKeyException>( Assert.Throws<NoSuchKeyException>(
delegate delegate
@ -152,7 +148,7 @@ namespace NFC_Test
SW2 = 0x7E SW2 = 0x7E
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<LengthErrorException>( Assert.Throws<LengthErrorException>(
delegate delegate
@ -170,7 +166,7 @@ namespace NFC_Test
SW2 = 0x9D SW2 = 0x9D
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<PermissionDeniedException>( Assert.Throws<PermissionDeniedException>(
delegate delegate
@ -189,7 +185,7 @@ namespace NFC_Test
SW2 = 0x9E SW2 = 0x9E
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ParameterErrorException>( Assert.Throws<ParameterErrorException>(
delegate delegate
@ -208,7 +204,7 @@ namespace NFC_Test
SW2 = 0xAD SW2 = 0xAD
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<AuthenticationDelayException>( Assert.Throws<AuthenticationDelayException>(
delegate delegate
@ -226,7 +222,7 @@ namespace NFC_Test
SW2 = 0xAE SW2 = 0xAE
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<AuthenticationErrorException>( Assert.Throws<AuthenticationErrorException>(
delegate delegate
@ -244,7 +240,7 @@ namespace NFC_Test
SW2 = 0xAF SW2 = 0xAF
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response); desfire.CheckAPDUResponse(response);
} }
@ -258,7 +254,7 @@ namespace NFC_Test
SW2 = 0xBE SW2 = 0xBE
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<BoundaryErrorException>( Assert.Throws<BoundaryErrorException>(
delegate delegate
@ -276,7 +272,7 @@ namespace NFC_Test
SW2 = 0xCA SW2 = 0xCA
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<CommandAbortedException>( Assert.Throws<CommandAbortedException>(
delegate delegate
@ -294,7 +290,7 @@ namespace NFC_Test
SW2 = 0xDE SW2 = 0xDE
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<DuplicateErrorException>( Assert.Throws<DuplicateErrorException>(
delegate delegate
@ -312,7 +308,7 @@ namespace NFC_Test
SW2 = 0xF0 SW2 = 0xF0
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<FileNotFoundException>( Assert.Throws<FileNotFoundException>(
delegate delegate
@ -336,7 +332,7 @@ namespace NFC_Test
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] lastblock = desfire.ExtractLastBlock(data, 8); byte[] lastblock = desfire.ExtractLastBlock(data, 8);
@ -351,7 +347,7 @@ namespace NFC_Test
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentException>( Assert.Throws<ArgumentException>(
delegate delegate
@ -365,7 +361,7 @@ namespace NFC_Test
{ {
byte[] data = null; byte[] data = null;
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>( Assert.Throws<ArgumentNullException>(
delegate delegate
@ -387,7 +383,7 @@ namespace NFC_Test
0x02, 0x03, 0x04, 0x01 0x02, 0x03, 0x04, 0x01
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_left = desfire.RotateLeft(data); byte[] data_left = desfire.RotateLeft(data);
@ -397,7 +393,7 @@ namespace NFC_Test
[Test] [Test]
public void RotateLeft_Null() public void RotateLeft_Null()
{ {
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>( Assert.Throws<ArgumentNullException>(
delegate delegate
@ -419,7 +415,7 @@ namespace NFC_Test
0x04, 0x01, 0x02, 0x03 0x04, 0x01, 0x02, 0x03
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_left = desfire.RotateRight(data); byte[] data_left = desfire.RotateRight(data);
@ -429,7 +425,7 @@ namespace NFC_Test
[Test] [Test]
public void RotateRight_Null() public void RotateRight_Null()
{ {
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>( Assert.Throws<ArgumentNullException>(
delegate delegate
@ -456,17 +452,47 @@ namespace NFC_Test
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_c = desfire.Concatenate(data_a, data_b); byte[] data_c = desfire.Concatenate(data_a, data_b);
Assert.AreEqual(expected_data_c, data_c); Assert.AreEqual(expected_data_c, data_c);
} }
[Test]
public void Concatenate_ABC()
{
byte[] data_a = new byte[]
{
0x01, 0x02, 0x03, 0x04
};
byte[] data_b = new byte[]
{
0x05, 0x06, 0x07, 0x08
};
byte[] data_c = new byte[]
{
0x09, 0xA0, 0xB0, 0xC0
};
byte[] expected_data_d = new byte[]
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xA0, 0xB0, 0xC0
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_d = desfire.Concatenate(data_a, data_b, data_c);
Assert.AreEqual(expected_data_d, data_d);
}
[Test] [Test]
public void Concatenate_Null() public void Concatenate_Null()
{ {
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>( Assert.Throws<ArgumentNullException>(
delegate delegate
@ -493,7 +519,7 @@ namespace NFC_Test
0x0F, 0xF0, 0x0F, 0xF0 0x0F, 0xF0, 0x0F, 0xF0
}; };
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_c = desfire.XOR(data_a, data_b); byte[] data_c = desfire.XOR(data_a, data_b);
@ -503,7 +529,7 @@ namespace NFC_Test
[Test] [Test]
public void XOR_null() public void XOR_null()
{ {
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>( Assert.Throws<ArgumentNullException>(
delegate delegate
@ -515,7 +541,7 @@ namespace NFC_Test
[Test] [Test]
public void GenerateSessionKey_AES() public void GenerateSessionKey_AES()
{ {
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] rndA = desfire.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91"); byte[] rndA = desfire.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91");
Console.WriteLine(desfire.ConvertToHexString(rndA)); Console.WriteLine(desfire.ConvertToHexString(rndA));
@ -537,31 +563,31 @@ namespace NFC_Test
{ {
ICard card = Substitute.For<ICard>(); ICard card = Substitute.For<ICard>();
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response_challenge_request = new APDUResponse() APDUResponse response_challenge_request = new APDUResponse()
{ {
SW1 = 0x91, SW1 = 0x91,
SW2 = 0xAF, SW2 = 0xAF,
Body = desfire.ConvertFromHexString("5D994CE085F24089") Body = HexConverter.ConvertFromHexString("5D994CE085F24089")
}; };
APDUResponse response_challenge_response = new APDUResponse() APDUResponse response_challenge_response = new APDUResponse()
{ {
SW1 = 0x91, SW1 = 0x91,
SW2 = 0x00, SW2 = 0x00,
Body = desfire.ConvertFromHexString("913C6DED84221C41") Body = HexConverter.ConvertFromHexString("913C6DED84221C41")
}; };
byte[] rndA = desfire.ConvertFromHexString("849B36C5F8BF4A09"); byte[] rndA = HexConverter.ConvertFromHexString("849B36C5F8BF4A09");
byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000"); byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0x1A)).Returns(response_challenge_request); card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0x1A)).Returns(response_challenge_request);
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAF)).Returns(response_challenge_response); card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAF)).Returns(response_challenge_response);
desfire.AuthenticateISO_DES(0x00, key, rndA); desfire.AuthenticateISO_DES(0x00, key, rndA);
byte[] expected_sessionkey = desfire.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759"); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759");
byte[] expected_iv = desfire.GenerateEmptyKey(8); byte[] expected_iv = desfire.GenerateEmptyKey(8);
Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_sessionkey, desfire._SessionKey);
@ -573,31 +599,31 @@ namespace NFC_Test
{ {
ICard card = Substitute.For<ICard>(); ICard card = Substitute.For<ICard>();
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response_challenge_request = new APDUResponse() APDUResponse response_challenge_request = new APDUResponse()
{ {
SW1 = 0x91, SW1 = 0x91,
SW2 = 0xAF, SW2 = 0xAF,
Body = desfire.ConvertFromHexString("43a28e28c653df83cd85039714bccb51") Body = HexConverter.ConvertFromHexString("43a28e28c653df83cd85039714bccb51")
}; };
APDUResponse response_challenge_response = new APDUResponse() APDUResponse response_challenge_response = new APDUResponse()
{ {
SW1 = 0x91, SW1 = 0x91,
SW2 = 0x00, SW2 = 0x00,
Body = desfire.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f") Body = HexConverter.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f")
}; };
byte[] rndA = desfire.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1"); byte[] rndA = HexConverter.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1");
byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000"); byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAA)).Returns(response_challenge_request); card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAA)).Returns(response_challenge_request);
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAF)).Returns(response_challenge_response); card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAF)).Returns(response_challenge_response);
desfire.AuthenticateISO_AES(0x00, key, rndA); desfire.AuthenticateISO_AES(0x00, key, rndA);
byte[] expected_sessionkey = desfire.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703"); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703");
byte[] expected_iv = desfire.GenerateEmptyKey(16); byte[] expected_iv = desfire.GenerateEmptyKey(16);
Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_sessionkey, desfire._SessionKey);
@ -609,7 +635,7 @@ namespace NFC_Test
{ {
ICard card = Substitute.For<ICard>(); ICard card = Substitute.For<ICard>();
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response = new APDUResponse() APDUResponse response = new APDUResponse()
{ {
@ -617,10 +643,10 @@ namespace NFC_Test
SW2 = 0x00 SW2 = 0x00
}; };
byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); byte[] new_key = HexConverter.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530");
byte[] sessionkey = desfire.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3"); byte[] sessionkey = HexConverter.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3");
byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
desfire._SessionKey = sessionkey; desfire._SessionKey = sessionkey;
desfire._IV = iv; desfire._IV = iv;
@ -635,7 +661,7 @@ namespace NFC_Test
{ {
ICard card = Substitute.For<ICard>(); ICard card = Substitute.For<ICard>();
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response = new APDUResponse() APDUResponse response = new APDUResponse()
{ {
@ -643,11 +669,11 @@ namespace NFC_Test
SW2 = 0x00 SW2 = 0x00
}; };
byte[] new_key = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12"); byte[] new_key = HexConverter.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12");
byte[] old_key = desfire.ConvertFromHexString("00000000000000000000000000000000"); byte[] old_key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
byte[] sessionkey = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); byte[] sessionkey = HexConverter.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b");
byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
desfire._SessionKey = sessionkey; desfire._SessionKey = sessionkey;
desfire._IV = iv; desfire._IV = iv;
@ -657,5 +683,27 @@ namespace NFC_Test
desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10); desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10);
} }
#endregion #endregion
#region Configuration Generator
[Test]
public void GenerateFileAccessRights()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.AreEqual(0x1234, desfire.GenerateFileAccessRights(0x01, 0x02, 0x03, 0x04));
}
[Test]
public void GenerateFileAccessRights_OutOfRange()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentOutOfRangeException>(
delegate
{
desfire.GenerateFileAccessRights(0x10, 0x00, 0x00, 0x00);
});
}
#endregion
} }
} }

View File

@ -1,14 +1,11 @@
using log4net; using log4net.Config;
using log4net.Config;
using NUnit.Framework; using NUnit.Framework;
using System;
namespace NFC_Test namespace NFC_Test
{ {
[SetUpFixture] [SetUpFixture]
public class NamespaceSetUp public class NamespaceSetUp
{ {
private static readonly ILog log = LogManager.GetLogger(typeof(NamespaceSetUp));
[OneTimeSetUp] [OneTimeSetUp]
public void OneTimeSetUp() public void OneTimeSetUp()
{ {

View File

@ -3,6 +3,8 @@ using NFC;
using NFC.Readers.PCSC; using NFC.Readers.PCSC;
using NFC.Mifare_DESFire; using NFC.Mifare_DESFire;
using NFC.Mifare_DESFire.Enums; using NFC.Mifare_DESFire.Enums;
using System;
using System.Text;
namespace NFC_Test namespace NFC_Test
{ {
@ -23,7 +25,7 @@ namespace NFC_Test
{ {
card.Connect(); card.Connect();
MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); MIFARE_DESFire desfire = new MIFARE_DESFire(card);
desfire.SelectApplication(0x000000); desfire.SelectApplication(0x000000);
desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16)); desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16));
@ -49,6 +51,15 @@ namespace NFC_Test
desfire.AuthenticateISO_AES(0x00, key_master); desfire.AuthenticateISO_AES(0x00, key_master);
desfire.ChangeOtherKey_AES(0x02, key_2, desfire.GenerateEmptyKey(16), 0x10); desfire.ChangeOtherKey_AES(0x02, key_2, desfire.GenerateEmptyKey(16), 0x10);
UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00);
desfire.CreateFile_Standard(0x01, FileCommunication.PLAIN, accesRights, 0x100);
desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("user@domain.org"));
byte[] data = desfire.ReadData(0x01, 0, 32);
Console.WriteLine(Encoding.ASCII.GetString(data));
transmit_successfully = true; transmit_successfully = true;
card.Disconnect(); card.Disconnect();

View File

@ -58,275 +58,5 @@ namespace NFC_Test
reader.Stop(); reader.Stop();
reader.CardDiscovered -= handler; reader.CardDiscovered -= handler;
} }
[TestCase("ACS ACR122U PICC Interface 0")]
public void GetApplicationIDs(string readerID)
{
IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(readerID);
bool transmit_successfully = false;
ReaderEventHandler handler = (sender, card) =>
{
card.Connect();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
//APDUCommand cmd = desfire.GetApplicationIDs();
//APDUResponse response = card.Transmit(cmd);
//if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
//{
// UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response);
// foreach(UInt32 id in ApplicationIDs)
// {
// Console.WriteLine("0x{0:X3}", id);
// }
// transmit_successfully = true;
//}
card.Disconnect();
};
reader.CardDiscovered += handler;
reader.Start();
Assert.AreEqual(true, transmit_successfully);
reader.Stop();
reader.CardDiscovered -= handler;
}
[TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)]
public void SelectApplication(string readerID, UInt32 applicationID)
{
IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(readerID);
bool transmit_successfully = false;
ReaderEventHandler handler = (sender, card) =>
{
card.Connect();
//MIFARE_DESFire desfire = new MIFARE_DESFire(card);
//APDUCommand cmd = desfire.SelectApplication(applicationID);
//cmd.ToArray();
//APDUResponse response = card.Transmit(cmd);
//if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
//{
// transmit_successfully = true;
//}
card.Disconnect();
};
reader.CardDiscovered += handler;
reader.Start();
Assert.AreEqual(true, transmit_successfully);
reader.Stop();
reader.CardDiscovered -= handler;
}
[TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)]
public void CreateApplication(string readerID, UInt32 applicationID)
{
//IHardware hardware = new Hardware();
//IReader reader = hardware.OpenReader(readerID);
//bool transmit_successfully = false;
//ReaderEventHandler handler = (sender, card) =>
//{
// card.Connect();
// MIFARE_DESFire desfire = new MIFARE_DESFire(card);
// byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE);
// byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.TDES, FileIdentifies.NOTUSED, 0x03);
// APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2);
// Console.WriteLine(cmd.ToArray());
// APDUResponse response = card.Transmit(cmd);
// if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
// {
// transmit_successfully = true;
// }
// card.Disconnect();
//};
//reader.CardDiscovered += handler;
//reader.Start();
//Assert.AreEqual(true, transmit_successfully);
//reader.Stop();
//reader.CardDiscovered -= handler;
}
[TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)]
public void DeleteApplication(string readerID, UInt32 applicationID)
{
IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(readerID);
bool transmit_successfully = false;
ReaderEventHandler handler = (sender, card) =>
{
card.Connect();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
desfire.SelectApplication(0x000000);
desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
desfire.DeleteApplication(applicationID);
transmit_successfully = true;
card.Disconnect();
};
reader.CardDiscovered += handler;
reader.Start();
Assert.AreEqual(true, transmit_successfully);
reader.Stop();
reader.CardDiscovered -= handler;
}
public byte[] GenerateDefaultKey(int size)
{
List<byte> key = new List<byte>();
for(int i = 0; i < size; i++)
{
key.Add(0);
}
return key.ToArray();
}
/// <summary>
/// Used Default PICC Key with PICC authenticate
/// </summary>
/// <param name="readerID"></param>
[TestCase("ACS ACR122U PICC Interface 0")]
public void Authenticate(string readerID)
{
IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(readerID);
bool transmit_successfully = false;
ReaderEventHandler handler = (sender, card) =>
{
card.Connect();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
desfire.SelectApplication(0x000000);
desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
transmit_successfully = true;
card.Disconnect();
};
reader.CardDiscovered += handler;
reader.Start();
Assert.AreEqual(true, transmit_successfully);
reader.Stop();
reader.CardDiscovered -= handler;
}
[TestCase("ACS ACR122U PICC Interface 0")]
public void ChangeKey(string readerID)
{
IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(readerID);
bool transmit_successfully = false;
ReaderEventHandler handler = (sender, card) =>
{
card.Connect();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
desfire.SelectApplication(0xAAFFEE);
desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
desfire.ChangeKeyDES(0x00, GenerateDefaultKey(8), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF });
transmit_successfully = true;
card.Disconnect();
};
reader.CardDiscovered += handler;
reader.Start();
Assert.AreEqual(true, transmit_successfully);
reader.Stop();
reader.CardDiscovered -= handler;
}
[TestCase("ACS ACR122U PICC Interface 0")]
public void ChangeKey_Test(string readerID)
{
IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(readerID);
bool transmit_successfully = false;
ReaderEventHandler handler = (sender, card) =>
{
card.Connect();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
desfire.SelectApplication(0xAAFFEE);
desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xC4,
Data = GenerateDefaultKey(1 + 16 + 4 + 4)
// KEY_NO, KEY, CRC32, PADDING
};
card.Transmit(cmd);
transmit_successfully = true;
card.Disconnect();
};
reader.CardDiscovered += handler;
reader.Start();
Assert.AreEqual(true, transmit_successfully);
reader.Stop();
reader.CardDiscovered -= handler;
}
} }
} }

View File

@ -9,183 +9,183 @@ using System.Text;
namespace NFC_Test namespace NFC_Test
{ {
[TestFixture] //[TestFixture]
public class REAL_Windows_CardSetUp //public class REAL_Windows_CardSetUp
{ //{
public static UInt32 FabAccessAID = 0x001100; // public static UInt32 FabAccessAID = 0x001100;
public static string CardReaderID = "ACS ACR122U PICC Interface 0"; // public static string CardReaderID = "ACS ACR122U PICC Interface 0";
public static byte[] PICC_MasterKey = new byte[] // public static byte[] PICC_MasterKey = new byte[]
{ // {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; // };
public static byte[] APP_MasterKey = new byte[] // public static byte[] APP_MasterKey = new byte[]
{ // {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; // };
public static byte[] APP_Key_1 = new byte[] // public static byte[] APP_Key_1 = new byte[]
{ // {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; // };
public static byte[] APP_Key_2 = new byte[] // public static byte[] APP_Key_2 = new byte[]
{ // {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; // };
public static byte[] Empty_Key = new byte[] // public static byte[] Empty_Key = new byte[]
{ // {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; // };
public static byte FabAccessIdentFileID = 0x01; // public static byte FabAccessIdentFileID = 0x01;
public static string UserDomain = "user1@fabaccess.org"; // public static string UserDomain = "user1@fabaccess.org";
[Test] // [Test]
public void ResetCard() // public void ResetCard()
{ // {
IHardware hardware = new Hardware(); // IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(CardReaderID); // IReader reader = hardware.OpenReader(CardReaderID);
bool connected_successfully = false; // bool connected_successfully = false;
ReaderEventHandler handler = (sender, card) => // ReaderEventHandler handler = (sender, card) =>
{ // {
card.Connect(); // card.Connect();
MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
mifareDESFire.AuthenticateDES(0x01, PICC_MasterKey); // mifareDESFire.AuthenticateISO_DES(0x01, PICC_MasterKey);
mifareDESFire.Format(); // mifareDESFire.Format();
connected_successfully = true; // connected_successfully = true;
card.Disconnect(); // card.Disconnect();
}; // };
reader.CardDiscovered += handler; // reader.CardDiscovered += handler;
reader.Start(); // reader.Start();
Assert.AreEqual(true, connected_successfully); // Assert.AreEqual(true, connected_successfully);
reader.Stop(); // reader.Stop();
reader.CardDiscovered -= handler; // reader.CardDiscovered -= handler;
} // }
[Test] // [Test]
public void ProvisionCard() // public void ProvisionCard()
{ // {
IHardware hardware = new Hardware(); // IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(CardReaderID); // IReader reader = hardware.OpenReader(CardReaderID);
bool connected_successfully = false; // bool connected_successfully = false;
ReaderEventHandler handler = (sender, card) => // ReaderEventHandler handler = (sender, card) =>
{ // {
card.Connect(); // card.Connect();
MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
mifareDESFire.AuthenticateDES(0x01, APP_MasterKey); // mifareDESFire.AuthenticateISO_DES(0x01, APP_MasterKey);
mifareDESFire.CreateApplication(FabAccessAID); // mifareDESFire.CreateApplication(FabAccessAID);
mifareDESFire.SelectApplication(FabAccessAID); // mifareDESFire.SelectApplication(FabAccessAID);
mifareDESFire.AuthenticateDES(0x00, Empty_Key); // mifareDESFire.AuthenticateDES(0x00, Empty_Key);
mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey); // mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey);
mifareDESFire.AuthenticateDES(0x00, APP_MasterKey); // mifareDESFire.AuthenticateDES(0x00, APP_MasterKey);
mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1); // mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1);
connected_successfully = true; // connected_successfully = true;
card.Disconnect(); // card.Disconnect();
}; // };
reader.CardDiscovered += handler; // reader.CardDiscovered += handler;
reader.Start(); // reader.Start();
Assert.AreEqual(true, connected_successfully); // Assert.AreEqual(true, connected_successfully);
reader.Stop(); // reader.Stop();
reader.CardDiscovered -= handler; // reader.CardDiscovered -= handler;
} // }
[Test] // [Test]
public void SetUpUserCard() // public void SetUpUserCard()
{ // {
IHardware hardware = new Hardware(); // IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(CardReaderID); // IReader reader = hardware.OpenReader(CardReaderID);
bool connected_successfully = false; // bool connected_successfully = false;
ReaderEventHandler handler = (sender, card) => // ReaderEventHandler handler = (sender, card) =>
{ // {
card.Connect(); // card.Connect();
MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
mifareDESFire.SelectApplication(FabAccessAID); // mifareDESFire.SelectApplication(FabAccessAID);
mifareDESFire.AuthenticateDES(0x00, Empty_Key); // mifareDESFire.AuthenticateDES(0x00, Empty_Key);
UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00); // UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00);
mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90); // mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain)); // mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain));
connected_successfully = true; // connected_successfully = true;
card.Disconnect(); // card.Disconnect();
}; // };
reader.CardDiscovered += handler; // reader.CardDiscovered += handler;
reader.Start(); // reader.Start();
Assert.AreEqual(true, connected_successfully); // Assert.AreEqual(true, connected_successfully);
reader.Stop(); // reader.Stop();
reader.CardDiscovered -= handler; // reader.CardDiscovered -= handler;
} // }
[Test] // [Test]
public void AuthenticateCard() // public void AuthenticateCard()
{ // {
IHardware hardware = new Hardware(); // IHardware hardware = new Hardware();
IReader reader = hardware.OpenReader(CardReaderID); // IReader reader = hardware.OpenReader(CardReaderID);
bool connected_successfully = false; // bool connected_successfully = false;
ReaderEventHandler handler = (sender, card) => // ReaderEventHandler handler = (sender, card) =>
{ // {
card.Connect(); // card.Connect();
MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
mifareDESFire.SelectApplication(FabAccessAID); // mifareDESFire.SelectApplication(FabAccessAID);
byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000); // byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
string userdomain = enc.GetString(filedata); // string userdomain = enc.GetString(filedata);
Console.WriteLine(userdomain); // Console.WriteLine(userdomain);
mifareDESFire.AuthenticateDES(0x01, APP_Key_1); // mifareDESFire.AuthenticateDES(0x01, APP_Key_1);
connected_successfully = true; // connected_successfully = true;
card.Disconnect(); // card.Disconnect();
}; // };
reader.CardDiscovered += handler; // reader.CardDiscovered += handler;
reader.Start(); // reader.Start();
Assert.AreEqual(true, connected_successfully); // Assert.AreEqual(true, connected_successfully);
reader.Stop(); // reader.Stop();
reader.CardDiscovered -= handler; // reader.CardDiscovered -= handler;
} // }
} //}
} }