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];