Added: Files from Borepin Project

This commit is contained in:
TheJoKlLa 2021-03-30 22:51:02 +02:00
parent 2f9e936505
commit 3c43f83a89
44 changed files with 2317 additions and 0 deletions

23
NFC/APDUCommand.cs Normal file
View File

@ -0,0 +1,23 @@
using System;
namespace NFC
{
public class APDUCommand
{
private IsoCase case4Short;
public APDUCommand(IsoCase case4Short)
{
this.case4Short = case4Short;
}
public int CLA { get; internal set; }
public byte INS { get; internal set; }
public byte[] Data { get; internal set; }
internal byte[] ToArray()
{
throw new NotImplementedException();
}
}
}

9
NFC/APDUResponse.cs Normal file
View File

@ -0,0 +1,9 @@
namespace NFC
{
public class APDUResponse
{
public byte SW1 { get; internal set; }
public byte SW2 { get; internal set; }
public byte[] Body { get; internal set; }
}
}

View File

@ -0,0 +1,21 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
/// <summary>
/// hold the Access Rights for changing application keys (Change Key command)
/// </summary>
public enum ChangeApplicationKey : byte
{
/// <summary>
/// Application master key authentication is necessary to change any key (default)
/// </summary>
MASTERKEY = 0x00,
/// <summary>
/// Authentication with the key to be changed (same Key#) is necessary to change a key
/// </summary>
SAMEKEY = 0x0E,
/// <summary>
/// All keys (except application master key, see Bit 0) within this application are frozen
/// </summary>
ALLKEYS = 0x0F
}
}

View File

@ -0,0 +1,18 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
/// <summary>
/// codes whether the application master key is changeable
/// </summary>
public enum ChangeMasterKey : byte
{
/// <summary>
/// Application master key is not changeable anymore (frozen)
/// </summary>
FROZEN = 0x00,
/// <summary>
/// Application master key is changeable (authentication with the current application master key necessary, default)
/// </summary>
CHANGEABLE = 0x01,
}
}

View File

@ -0,0 +1,19 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
/// <summary>
/// codes whether a change of the application master key settings is allowed
/// </summary>
public enum ChangeMasterKeySettings : byte
{
/// <summary>
/// configuration not changeable anymore (frozen)
/// </summary>
FROZEN = 0x00,
/// <summary>
/// this configuration is changeable if authenticated with the application master key (default)
/// </summary>
WITHMASTERKEY = 0x08
}
}

View File

@ -0,0 +1,18 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
/// <summary>
/// codes whether application master key authentication is needed before “Create File” / “Delete File”
/// </summary>
public enum CreateDeleteFile : byte
{
/// <summary>
/// “Create File”/ “Delete File”is permitted only with application master key authentication
/// </summary>
ONLYMASTERKEY = 0x00,
/// <summary>
/// “Create File”/ “Delete File”is permitted also without application master key authentication (default)
/// </summary>
NOKEY = 0x04,
}
}

View File

@ -0,0 +1,12 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
/// <summary>
/// Crypto method of the application
/// </summary>
public enum CryptoOperationsType : byte
{
TDES = 0x00,
TKTDES = 0x40,
AES = 0x80,
}
}

View File

@ -0,0 +1,8 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
public enum FileAccessRights : byte
{
FREE = 0x0E,
NEVER = 0x0F
}
}

View File

@ -0,0 +1,20 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
public enum FileCommunication : byte
{
/// <summary>
/// "Plain communication"
/// </summary>
PLAIN = 0x00,
/// <summary>
/// Plain communication secured by DES/3DES MACing
/// </summary>
MAC = 0x01,
/// <summary>
/// Fully DES/3DES enciphered communication
/// </summary>
ENCRYPT = 0x03
}
}

View File

@ -0,0 +1,18 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
/// <summary>
/// codes whether application master key authentication is needed for file directory access
/// </summary>
public enum FileDirectoryAccess : byte
{
/// <summary>
/// Successful application master key authentication is required for executing the “Get FID List”, “Get File Settings”and “Get Key Settings”commands
/// </summary>
ONLYMASTERKEY = 0x00,
/// <summary>
/// “Get FID List”, “Get File Settings” and “Get Key Settings” commands succeed independentlyof a preceding application master key authentication (default)
/// </summary>
NOKEY = 0x02,
}
}

View File

@ -0,0 +1,11 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
/// <summary>
/// Indicates use of 2 byte ISO/IEC 7816-4 File Identifies for files within the Application
/// </summary>
public enum FileIdentifies : byte
{
NOTUSED = 0x00,
USED = 0x20
}
}

View File

@ -0,0 +1,30 @@
namespace NFC.Cards.NXP_MIFARE_DESFire.Enums
{
enum FileTypes : byte
{
/// <summary>
/// Standard Data File
/// </summary>
STANDARD = 0x00,
/// <summary>
/// Backup Data Files
/// </summary>
BACKUP = 0x01,
/// <summary>
/// Value Files with Backup
/// </summary>
VALUE = 0x02,
/// <summary>
/// Linear Record Files with Backup
/// </summary>
LINEARRECORD = 0x03,
/// <summary>
/// Cyclic Record Files with Backup
/// </summary>
CYCLICRECORD = 0x04
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Currently not allowed to authenticate. Keeptrying until full delay is spent.
/// 0x91AD
/// </summary>
public class AuthenticationDelayException : Exception
{
public AuthenticationDelayException()
{
}
public AuthenticationDelayException(string message) : base(message)
{
}
public AuthenticationDelayException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

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

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.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)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Attempt toread/write data from/to beyond thefiles/records limits. Attempt to exceed the limitsof a value file.
/// 0x91BE
/// </summary>
public class BoundaryErrorException : Exception
{
public BoundaryErrorException()
{
}
public BoundaryErrorException(string message) : base(message)
{
}
public BoundaryErrorException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Previous Command was not fully completed.Not all Frames were requested or provided bythe PCD.
/// 0x91CA
/// </summary>
public class CommandAbortedException : Exception
{
public CommandAbortedException()
{
}
public CommandAbortedException(string message) : base(message)
{
}
public CommandAbortedException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Creation of file/application failed because file/application with same number already exists
/// 0x91DE
/// </summary>
public class DuplicateErrorException : Exception
{
public DuplicateErrorException()
{
}
public DuplicateErrorException(string message) : base(message)
{
}
public DuplicateErrorException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Specified file number does not exist.
/// 0x91F0
/// </summary>
public class FileNotFoundException : Exception
{
public FileNotFoundException()
{
}
public FileNotFoundException(string message) : base(message)
{
}
public FileNotFoundException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Command code not supported.
/// 0x911C
/// </summary>
public class IllegalCommandCodeException : Exception
{
public IllegalCommandCodeException()
{
}
public IllegalCommandCodeException(string message) : base(message)
{
}
public IllegalCommandCodeException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// CRC or MAC does not match data. Paddingbytes not valid.
/// 0x911E
/// </summary>
public class IntegrityErrorException : Exception
{
public IntegrityErrorException()
{
}
public IntegrityErrorException(string message) : base(message)
{
}
public IntegrityErrorException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Length of command string invalid.
/// 0x917E
/// </summary>
public class LengthErrorException : Exception
{
public LengthErrorException()
{
}
public LengthErrorException(string message) : base(message)
{
}
public LengthErrorException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Invalid key number specified.
/// 0x9140
/// </summary>
public class NoSuchKeyException : Exception
{
public NoSuchKeyException()
{
}
public NoSuchKeyException(string message) : base(message)
{
}
public NoSuchKeyException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Value of the parameter(s) invalid.
/// 0x919E
/// </summary>
public class ParameterErrorException : Exception
{
public ParameterErrorException()
{
}
public ParameterErrorException(string message) : base(message)
{
}
public ParameterErrorException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Cards.NXP_MIFARE_DESFire.Exceptions
{
/// <summary>
/// Current configuration / status does not allow the requested command.
/// 0x919D
/// </summary>
public class PermissionDeniedException : Exception
{
public PermissionDeniedException()
{
}
public PermissionDeniedException(string message) : base(message)
{
}
public PermissionDeniedException(string message, Exception inner) : base(message, inner)
{
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
using System;
namespace NFC.Exceptions
{
public class APDUException : Exception
{
public readonly byte ResponseCode;
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace NFC.Exceptions
{
public class CardUnavailableException : Exception
{
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace NFC.Exceptions
{
public class ReaderUnavailableException : Exception
{
}
}

View File

@ -0,0 +1,44 @@
using System;
namespace NFC.Helper.Crypto.CRC
{
/// <summary>
/// CRC16 for DESFire Card
/// </summary>
public class CRC16
{
public UInt16 Polynomial { get; } = 0x8408;
public UInt16 InitValue { get; } = 0x6363;
public UInt16 Calculate(byte[] data, UInt16 crc16)
{
for (int i = 0; i < data.Length; i++)
{
crc16 ^= data[i];
for (int b = 0; b < 8; b++)
{
bool b_Bit = (crc16 & 0x01) > 0;
crc16 >>= 1;
if (b_Bit)
{
crc16 ^= Polynomial;
}
}
}
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

@ -0,0 +1,44 @@
using System;
namespace NFC.Helper.Crypto.CRC
{
/// <summary>
/// CRC32 for DESFire Card
/// </summary>
public class CRC32
{
public UInt32 Polynomial { get; } = 0xEDB88320;
public UInt32 InitValue { get; } = 0xFFFFFFFF;
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 ^= Polynomial;
}
}
}
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

@ -0,0 +1,48 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Helper.Crypto.Cipher
{
public class AES : ICipher
{
public uint BlockSize { get; } = 16;
public uint KeySize { get; } = 16;
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
AesEngine engine = new AesEngine();
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)
{
AesEngine engine = new AesEngine();
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

@ -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.Helper.Crypto.Cipher
{
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

@ -0,0 +1,48 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Helper.Crypto.Cipher
{
public class TDES_2K : ICipher
{
public uint BlockSize { get; } = 8;
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

@ -0,0 +1,48 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Helper.Crypto.Cipher
{
public class TDES_3K : ICipher
{
public uint BlockSize { get; } = 8;
public uint KeySize { get; } = 24;
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

@ -0,0 +1,182 @@
using System;
namespace NFC.Helper.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>
/// Creates Key from String
/// </summary>
/// <param name="key">Key</param>
/// <param name="cipher">Cipher for Key</param>
/// <param name="keyVersion">Version of Key</param>
public CipherKey(string key, CipherType cipher, byte keyVersion) : this(HexConverter.ConvertFromHexString(key), cipher, keyVersion)
{
}
/// <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 16;
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
}
}

View File

@ -0,0 +1,25 @@
namespace NFC.Helper.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
}
}

View File

@ -0,0 +1,32 @@
namespace NFC.Helper.Crypto
{
public interface ICipher
{
/// <summary>
/// Size of Cipher Block in Byte
/// </summary>
uint BlockSize { get; }
/// <summary>
/// Size of Key in Byte
/// </summary>
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>
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>
byte[] Decrypt(byte[] data, byte[] key, byte[] IV);
}
}

View File

@ -0,0 +1,51 @@
using System;
namespace NFC.Helper
{
/// <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));
}
}
}

22
NFC/Interfaces/ICard.cs Normal file
View File

@ -0,0 +1,22 @@
namespace NFC.Interfaces
{
public interface ICard
{
/// <summary>
/// Connect to Smartcard
/// </summary>
void Connect();
/// <summary>
/// Disconnect from Smartcard
/// </summary>
void Disconnect();
/// <summary>
/// Transmit APDU Command to Smartcard
/// </summary>
/// <param name="apdu_cmd">Application Protocol Data Unit Command - ISO 7816</param>
/// <returns>Application Protocol Data Unit Response - ISO 7816</returns>
APDUResponse Transmit(APDUCommand apdu_cmd);
}
}

View File

@ -0,0 +1,26 @@
using System;
namespace NFC.Interfaces
{
/// <summary>
/// Abstract representation of the platform specific NFC Hardware
/// </summary>
public interface IHardware
{
/// <summary>
/// Check if the device has nfc support
/// </summary>
/// <returns>Returns true if the device supports NFC</returns>
bool IsAvailable();
/// <returns>Returns all available readers</returns>
string[] GetReaders();
/// <summary>
/// Create a new reader instance from the specified id
/// </summary>
/// <returns>Returns the spatform specific reader that corresponds to the id</returns>
/// <exception cref="ArgumentException">Invalid reader id</exception>
IReader OpenReader(string readerID);
}
}

24
NFC/Interfaces/IReader.cs Normal file
View File

@ -0,0 +1,24 @@
namespace NFC.Interfaces
{
public delegate void ReaderEventHandler(object sender, ICard card);
/// <summary>
/// Abstraction of a platform-specifc reader that can communicate with NFC cards
/// </summary>
public interface IReader
{
/// <summary>
/// Event that will be called when a new tag was discovered
/// </summary>
event ReaderEventHandler CardDiscovered;
/// <summary>
/// Event that will be called when a tag that is in use gets disconnected
/// </summary>
event ReaderEventHandler CardLost;
void Start();
void Stop();
}
}

8
NFC/IsoCase.cs Normal file
View File

@ -0,0 +1,8 @@
namespace NFC
{
public enum IsoCase
{
Case4Short,
Case2Short
}
}

View File

@ -4,4 +4,9 @@
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="log4net" Version="2.0.12" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.10" />
</ItemGroup>
</Project> </Project>