mirror of
https://gitlab.com/fabinfra/fabaccess/borepin.git
synced 2025-06-11 02:53:23 +02:00
Added: Create STD File, ReadData, WriteData
This commit is contained in:
@ -2,26 +2,14 @@
|
||||
|
||||
namespace NFC.Crypto
|
||||
{
|
||||
/// <summary>
|
||||
/// CRC16 for DESFire Card
|
||||
/// </summary>
|
||||
public class CRC16
|
||||
{
|
||||
public byte[] Calculate(byte[] data)
|
||||
{
|
||||
UInt16 crc16 = 0x6363;
|
||||
public UInt16 Polynomial { get; } = 0x8408;
|
||||
|
||||
crc16 = Calculate(data, crc16);
|
||||
|
||||
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 InitValue { get; } = 0x6363;
|
||||
|
||||
public UInt16 Calculate(byte[] data, UInt16 crc16)
|
||||
{
|
||||
@ -34,11 +22,23 @@ namespace NFC.Crypto
|
||||
crc16 >>= 1;
|
||||
if (b_Bit)
|
||||
{
|
||||
crc16 ^= 0x8408;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +1,15 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace NFC.Crypto
|
||||
{
|
||||
/// <summary>
|
||||
/// CRC32 for DESFire Card
|
||||
/// </summary>
|
||||
public class CRC32
|
||||
{
|
||||
public byte[] Calculate(byte[] data)
|
||||
{
|
||||
UInt32 crc32 = 0xFFFFFFFF;
|
||||
public UInt32 Polynomial { get; } = 0xEDB88320;
|
||||
|
||||
crc32 = Calculate(data, crc32);
|
||||
|
||||
return BitConverter.GetBytes(crc32);
|
||||
}
|
||||
|
||||
public byte[] Calculate(byte[] cmd, byte[] data)
|
||||
{
|
||||
UInt32 crc32 = 0xFFFFFFFF;
|
||||
|
||||
crc32 = Calculate(cmd, crc32);
|
||||
crc32 = Calculate(data, crc32);
|
||||
|
||||
return BitConverter.GetBytes(crc32);
|
||||
}
|
||||
public UInt32 InitValue { get; } = 0xFFFFFFFF;
|
||||
|
||||
public UInt32 Calculate(byte[] data, UInt32 crc32)
|
||||
{
|
||||
@ -35,11 +22,23 @@ namespace NFC.Crypto
|
||||
crc32 >>= 1;
|
||||
if (b_Bit)
|
||||
{
|
||||
crc32 ^= 0xEDB88320;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
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)
|
||||
{
|
||||
AesEngine engine = new AesEngine();
|
49
NFC/Crypto/Cipher/TDES.cs
Normal file
49
NFC/Crypto/Cipher/TDES.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
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)
|
||||
{
|
||||
DesEngine engine = new DesEdeEngine();
|
@ -1,16 +1,19 @@
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
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)
|
||||
{
|
||||
DesEngine engine = new DesEngine();
|
||||
DesEngine engine = new DesEdeEngine();
|
||||
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
|
||||
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
|
||||
KeyParameter keyParam = new KeyParameter(key);
|
||||
@ -27,7 +30,7 @@ namespace NFC.Crypto
|
||||
|
||||
public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
|
||||
{
|
||||
DesEngine engine = new DesEngine();
|
||||
DesEngine engine = new DesEdeEngine();
|
||||
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
|
||||
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
|
||||
KeyParameter keyParam = new KeyParameter(key);
|
171
NFC/Crypto/CipherKey.cs
Normal file
171
NFC/Crypto/CipherKey.cs
Normal 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
25
NFC/Crypto/CipherType.cs
Normal 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
32
NFC/Crypto/ICipher.cs
Normal 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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user