diff --git a/src/MiFare/Classic/ICardReader.cs b/src/MiFare/Classic/ICardReader.cs index e8b3764..eb1f40f 100644 --- a/src/MiFare/Classic/ICardReader.cs +++ b/src/MiFare/Classic/ICardReader.cs @@ -61,6 +61,17 @@ interface ICardReader /// tru on success, false otherwise Task Login(int sector, InternalKeyType key); + /// + /// Tests if login into the given sector using the given key is possible + /// + /// sector to login into + /// keytype to use (e.g. KeyA, KeyB) + /// key to use + /// tru on success, false otherwise + Task TestLogin(int sector,KeyType keytype, byte[] key); + + + /// /// read a datablock from a sector /// diff --git a/src/MiFare/Classic/MiFARECard.cs b/src/MiFare/Classic/MiFARECard.cs index 4854ff9..4dab856 100644 --- a/src/MiFare/Classic/MiFARECard.cs +++ b/src/MiFare/Classic/MiFARECard.cs @@ -231,6 +231,20 @@ public async Task SetData(int sector, int dataBlock, byte[] data) } } + + + /// + /// Tests if login into the given sector using the given key is possible + /// + /// sector to login into + /// keytype to use (e.g. KeyA, KeyB) + /// key to use + /// tru on success, false otherwise + public async Task TestLogin(int sector, KeyType keytype, byte[] key) + { + return await GetSector(sector).TestLogin(keytype, key); + } + /// /// reinitialize the object /// diff --git a/src/MiFare/Classic/MiFareStandardCardReaderBase.cs b/src/MiFare/Classic/MiFareStandardCardReaderBase.cs index ad4dcc8..d255329 100644 --- a/src/MiFare/Classic/MiFareStandardCardReaderBase.cs +++ b/src/MiFare/Classic/MiFareStandardCardReaderBase.cs @@ -22,9 +22,9 @@ abstract class MiFareStandardCardReaderBase : ICardReader, IDisposable private Dictionary keyMap = new Dictionary(); - private byte nextKeySlot; + private static byte nextKeySlot; - private Dictionary keyToLocationMap = new Dictionary(KeyEqualityComparer.Default); + private static Dictionary keyToLocationMap = new Dictionary(KeyEqualityComparer.Default); protected MiFareStandardCardReaderBase(IReadOnlyCollection keys) { @@ -111,6 +111,33 @@ public async Task Login(int sector, InternalKeyType key) return res.Succeeded; } + public async Task TestLogin(int sector, KeyType keytype, byte[] key) + { + //for testing we ignore the keymap + var gaKeyType = (GeneralAuthenticate.GeneralAuthenticateKeyType)keytype; + + // Get the block for the sector + var blockNumber = SectorToBlock(sector, 0); + + // see if we have the key loaded already + byte location; + if (!keyToLocationMap.TryGetValue(key, out location)) + { + location = nextKeySlot; + nextKeySlot++; + keyToLocationMap[key] = location; + + // Load the key to the location + var r = await TransceiveAsync(new LoadKey(key, location)); + if (!r.Succeeded) + return false; // could not load the key + } + + var res = await TransceiveAsync(new PcSc.MiFareStandard.GeneralAuthenticate(blockNumber, location, gaKeyType)); + + return res.Succeeded; + } + public async Task> Read(int sector, int datablock) { var blockNumber = SectorToBlock(sector, datablock); diff --git a/src/MiFare/Classic/Sector.cs b/src/MiFare/Classic/Sector.cs index 995ace7..cffc3fe 100644 --- a/src/MiFare/Classic/Sector.cs +++ b/src/MiFare/Classic/Sector.cs @@ -205,6 +205,11 @@ private async Task FlushDataBlock(DataBlock dataBlock) throw new CardWriteException($"Unable to write in sector {sector}, block {dataBlock.Number}"); } + public async Task TestLogin(KeyType keytype, byte[] key) + { + return await card.Reader.TestLogin(sector, keytype, key); + } + private async Task GetDataBlockInt(int block) { var db = dataBlocks[block];