From c943a51d9ce18dc18b20509297f2be4fa30aada1 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Thu, 1 Oct 2020 19:06:09 +0200 Subject: [PATCH] BackUp DES --- NFC/Crypto/DES.cs | 45 ++++++++++ NFC/Crypto/TripleDES.cs | 45 ++++++++++ NFC/Mifare DESFire/MifareDESFire.cs | 127 ++++++++++++++++++++++++++- NFC/NFC.csproj | 3 +- NFC_Test/AuthCrypto_Test.cs | 129 ++++++++++++++++++++++++++++ NFC_Test/MifareDESFire_Commands.cs | 5 +- NFC_Test/NFC_Test.csproj | 1 + NFC_Test/REAL_Windows.cs | 44 ++++++++++ NFC_Test/REAL_Windows_CardSetUp.cs | 2 +- 9 files changed, 393 insertions(+), 8 deletions(-) create mode 100644 NFC/Crypto/DES.cs create mode 100644 NFC/Crypto/TripleDES.cs create mode 100644 NFC_Test/AuthCrypto_Test.cs diff --git a/NFC/Crypto/DES.cs b/NFC/Crypto/DES.cs new file mode 100644 index 0000000..db9356a --- /dev/null +++ b/NFC/Crypto/DES.cs @@ -0,0 +1,45 @@ +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 byte[] Encrypt(byte[] data, byte[] key, byte[] iv) + { + DesEngine engine = new DesEngine(); + 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 DesEngine(); + 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; + } + } +} diff --git a/NFC/Crypto/TripleDES.cs b/NFC/Crypto/TripleDES.cs new file mode 100644 index 0000000..bf4c4fe --- /dev/null +++ b/NFC/Crypto/TripleDES.cs @@ -0,0 +1,45 @@ +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 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; + } + } +} diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/Mifare DESFire/MifareDESFire.cs index 14dd282..c6617b7 100644 --- a/NFC/Mifare DESFire/MifareDESFire.cs +++ b/NFC/Mifare DESFire/MifareDESFire.cs @@ -1,13 +1,28 @@ -using NFC.Mifare_DESFire.Enums; +using NFC.Crypto; +using NFC.Mifare_DESFire.Enums; using PCSC.Iso7816; using System; using System.Collections.Generic; +using System.IO; +using System.Net.Http; using System.Text; namespace NFC.Mifare_DESFire { + public class MifareDESFire { + public byte[] GenerateDefaultKey(int size) + { + List key = new List(); + for (int i = 0; i < size; i++) + { + key.Add(0); + } + + return key.ToArray(); + } + private ICard _Card; public MifareDESFire(ICard card) @@ -59,9 +74,113 @@ namespace NFC.Mifare_DESFire throw new NotImplementedException(); } - public void Authenticate(int v, byte[] aPP_MasterKey) + /// + /// Authenticate to Card + /// + /// 0x01 - 0x0D + /// + public void Authenticate(byte key_id, byte[] key) { - throw new NotImplementedException(); + APDUCommand cmd_getchallange = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)0x1A, + Data = new byte[] + { + key_id + } + }; + APDUResponse response = _Card.Transmit(cmd_getchallange); + + byte[] challenge = response.Body; + Console.WriteLine("Challange: {0}", toHexString(challenge)); + + byte[] rndA = new byte[] + { + 0x92, 0x31, 0x34, 0x8B, 0x66, 0x35, 0xA8, 0xAF + }; + Console.WriteLine("rndA: {0}", toHexString(rndA)); + + TripleDES des = new TripleDES(); + byte[] rndB = des.Decrypt(challenge, key, GenerateDefaultKey(8)); + Console.WriteLine("rndB: {0}", toHexString(rndB)); + + byte[] leftRotatedRndB = rotateLeft(rndB); + Console.WriteLine("leftRotatedRndB: {0}", toHexString(leftRotatedRndB)); + + byte[] rndA_rndB = concatenate(rndA, leftRotatedRndB); + Console.WriteLine("rndA_rndB: {0}", toHexString(rndA_rndB)); + + byte[] challengeAnswer = des.Encrypt(rndA_rndB, key, GenerateDefaultKey(8)); + Console.WriteLine("challengeAnswer: {0}", toHexString(challengeAnswer)); + + APDUCommand cmd_answerchallange = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)0xAF, + Data = challengeAnswer + }; + Console.WriteLine("cmd_answerchallange: {0}", toHexString(cmd_answerchallange.ToArray())); + + response = _Card.Transmit(cmd_answerchallange); + + byte[] encryptedRndAFromCard = response.Body; + Console.WriteLine("encryptedRndAFromCard: {0}", toHexString(encryptedRndAFromCard)); + + byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, GenerateDefaultKey(8)); + Console.WriteLine("rotatedRndAFromCard: {0}", toHexString(rotatedRndAFromCard)); + + byte[] rndAFromCard = rotateRight(rotatedRndAFromCard); + Console.WriteLine("rndAFromCard: {0}", toHexString(rndAFromCard)); + + if (!rndA.Equals(rndAFromCard)) + { + throw new Exception("???"); + } + } + + private String toHexString(byte[] data) + { + return BitConverter.ToString(data).Replace("-", string.Empty); + } + + public byte[] rotateLeft(byte[] data) + { + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte temp = rotate[0]; + for (var i = 0; i < rotate.Length - 1; i++) + { + rotate[i] = rotate[i + 1]; + } + rotate[rotate.Length - 1] = temp; + + return rotate; + } + + public byte[] rotateRight(byte[] data) + { + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte temp = rotate[rotate.Length - 1]; + for (var i = rotate.Length - 1; i > 1; i--) + { + rotate[i] = rotate[i - 1]; + } + rotate[0] = temp; + + return rotate; + } + + public byte[] concatenate(byte[] a, byte[] b) + { + byte[] c = new byte[a.Length + b.Length]; + a.CopyTo(c, 0); + b.CopyTo(c, a.Length); + + return c; } /// @@ -148,7 +267,7 @@ namespace NFC.Mifare_DESFire return cmd; } - public void CreateFile(byte fabAccessIdentFileID, FileCommunication pLAIN, ushort fileAccessRight, int v) + public void CreateFile(byte fabAccessIdentFileID, FileCommunication pLAIN, ushort fileAccessRight, UInt32 v) { throw new NotImplementedException(); } diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj index 519a331..59bc652 100644 --- a/NFC/NFC.csproj +++ b/NFC/NFC.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,5 +7,6 @@ + diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs new file mode 100644 index 0000000..04d2856 --- /dev/null +++ b/NFC_Test/AuthCrypto_Test.cs @@ -0,0 +1,129 @@ +using NFC; +using NFC.Crypto; +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 key = new List(); + 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() + { + MifareDESFire mifareDESFire = new MifareDESFire(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(); + + card.Transmit(cmd_getchallange).ReturnsForAnyArgs(response); + card.Transmit(cmd_answerchallange).Returns(response2); + + MifareDESFire mifareDESFire = new MifareDESFire(card); + + mifareDESFire.Authenticate(0x00, mifareDESFire.GenerateDefaultKey(16)); + } + } +} diff --git a/NFC_Test/MifareDESFire_Commands.cs b/NFC_Test/MifareDESFire_Commands.cs index 79207bd..436d92d 100644 --- a/NFC_Test/MifareDESFire_Commands.cs +++ b/NFC_Test/MifareDESFire_Commands.cs @@ -1,5 +1,6 @@ using NFC; using NFC.Mifare_DESFire; +using NFC.Mifare_DESFire.Enums; using NUnit.Framework; using System; using System.Collections.Generic; @@ -15,7 +16,7 @@ namespace NFC_Test [SetUp] public void SetUp() { - _MifareDESFire = new MifareDESFire(); + //_MifareDESFire = new MifareDESFire(); } [Test] @@ -27,7 +28,7 @@ namespace NFC_Test [Test] public void GenerateKeySetting1() { - Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(MifareDESFire.ChangeApplicationKey.SAMEKEY, MifareDESFire.ChangeMasterKeySettings.WITHMASTERKEY, MifareDESFire.CreateDeleteFile.NOKEY, MifareDESFire.FileDirectoryAccess.NOKEY, MifareDESFire.ChangeMasterKey.CHANGEABLE)); + Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE)); } } } diff --git a/NFC_Test/NFC_Test.csproj b/NFC_Test/NFC_Test.csproj index df2e516..d420e5c 100644 --- a/NFC_Test/NFC_Test.csproj +++ b/NFC_Test/NFC_Test.csproj @@ -6,6 +6,7 @@ + diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index 12f9701..85ffafb 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -212,5 +212,49 @@ namespace NFC_Test reader.Stop(); reader.CardDiscovered -= handler; } + + public byte[] GenerateDefaultKey(int size) + { + List key = new List(); + for(int i = 0; i < size; i++) + { + key.Add(0); + } + + return key.ToArray(); + } + /// + /// Used Default PICC Key with PICC authenticate + /// + /// + [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(); + + MifareDESFire desfire = new MifareDESFire(card); + + desfire.Authenticate(0x00, GenerateDefaultKey(8)); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } } } diff --git a/NFC_Test/REAL_Windows_CardSetUp.cs b/NFC_Test/REAL_Windows_CardSetUp.cs index 67b9061..bb8c7e0 100644 --- a/NFC_Test/REAL_Windows_CardSetUp.cs +++ b/NFC_Test/REAL_Windows_CardSetUp.cs @@ -56,7 +56,7 @@ namespace NFC_Test MifareDESFire mifareDESFire = new MifareDESFire(card); - mifareDESFire.Authenticate(0x01, APP_MasterKey); + mifareDESFire.Authenticate(0x01, PICC_MasterKey); mifareDESFire.Format();