Mifare Classic身份验证故障在某些设备上,直到使用Mifare Classic工具读取标签

发布于 2025-01-23 21:58:37 字数 3046 浏览 3 评论 0原文

我正在尝试在Xamarin表单Android应用程序中读取Mifare经典卡的扇区0块的用户数据。在大多数设备上,它每次都可以完美地工作,但是在Unitech EA510上,身份验证始终失败,除非我首先使用Mifare Classic工具阅读卡(

  1. 第一次使用应用程序扫描标签: Mifare经典标签身份验证失败:8250A9B9
  2. 使用Mifare Classic Tool用
  3. 应用程序重新扫描标签: Mifare经典标签找到:8250A9B9 10240472
  4. 扫描App的标签另一个标签: Mifare经典标签找到:8250A9C7 10395802
public void OnTagDiscovered(Android.Nfc.Tag tag)
{
    string tagId = string.Empty;
    string[] techList = tag.GetTechList();
    string sUid = string.Empty;
    if (Array.IndexOf(techList, "android.nfc.tech.MifareClassic") > -1) {
        MifareClassic mfc = null;
        try {
            sUid = BitConverter.ToString(tag.GetId()).Replace("-", "");
            mfc = MifareClassic.Get(tag);
            mfc.Connect();
            bool bAuthenticated = false;
            if (mfc.AuthenticateSectorWithKeyA(0, MifareClassic.KeyDefault.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyB(0, MifareClassic.KeyDefault.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyA(0, MifareClassic.KeyMifareApplicationDirectory.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyB(0, MifareClassic.KeyMifareApplicationDirectory.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyA(0, MifareClassic.KeyNfcForum.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyB(0, MifareClassic.KeyNfcForum.ToArray()))
                bAuthenticated = true;
            if (bAuthenticated) {
                int blockOffset = mfc.SectorToBlock(0);
                byte[] block = mfc.ReadBlock(blockOffset + 1); // Sector 0/block 0 is the UID so go straight to block 1 for the payload
                tagId = System.Text.Encoding.ASCII.GetString(block);
                if (tagId.Length == 1 && tagId[0] == 0x04)
                    // Ignore if ReadBlock returns a single byte 0x04, which appears to happen if there's a delay between the tag discovery and ReadBlock (e.g. running in the debugger) and we don't want to treat it as a conventional tag by acciden
                    tagId = string.Empty;
                else if (tagId.Length > 0 && tagId.Contains('\0')) 
                    tagId = tagId.Substring(0, tagId.IndexOf('\0'));
            } else {
                Console.WriteLine($"Mifare Classic tag authentication failure: {sUid}");
            }
        }
        catch (Exception ex) {
            Console.WriteLine($"Mifare Classic tag read exception: {ex.Message}");
        }
        finally {
            if (mfc != null && mfc.IsConnected)
                mfc.Close();
            if (tagId != string.Empty)
                Console.WriteLine($"Mifare Classic tag found: {sUid} {tagId}");
        }
    }
    if (tagId != string.Empty)
        Do stuff
}

I'm trying to read user data from sector 0 block 1 of Mifare Classic cards in a Xamarin Forms Android app. On most devices it works perfectly every time, but on a Unitech EA510 the authentication consistently fails UNLESS I first read the card using the Mifare Classic Tool (https://play.google.com/store/apps/details?id=de.syss.MifareClassicTool). As soon as I've detected any tag with the Mifare Classic Tool my code works perfectly every time. I've checked the Mifare Classic Tool source code to see what else it's doing and borrowed the patchTag logic (it didn't help!).

  1. Scan tag with the app first time:
    Mifare Classic tag authentication failure: 8250A9B9
  2. Scan tag using the Mifare Classic Tool
  3. Re-scan the tag with the app:
    Mifare Classic tag found: 8250A9B9 10240472
  4. Scan another the tag with the app:
    Mifare Classic tag found: 8250A9C7 10395802
public void OnTagDiscovered(Android.Nfc.Tag tag)
{
    string tagId = string.Empty;
    string[] techList = tag.GetTechList();
    string sUid = string.Empty;
    if (Array.IndexOf(techList, "android.nfc.tech.MifareClassic") > -1) {
        MifareClassic mfc = null;
        try {
            sUid = BitConverter.ToString(tag.GetId()).Replace("-", "");
            mfc = MifareClassic.Get(tag);
            mfc.Connect();
            bool bAuthenticated = false;
            if (mfc.AuthenticateSectorWithKeyA(0, MifareClassic.KeyDefault.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyB(0, MifareClassic.KeyDefault.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyA(0, MifareClassic.KeyMifareApplicationDirectory.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyB(0, MifareClassic.KeyMifareApplicationDirectory.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyA(0, MifareClassic.KeyNfcForum.ToArray()))
                bAuthenticated = true;
            else if (mfc.AuthenticateSectorWithKeyB(0, MifareClassic.KeyNfcForum.ToArray()))
                bAuthenticated = true;
            if (bAuthenticated) {
                int blockOffset = mfc.SectorToBlock(0);
                byte[] block = mfc.ReadBlock(blockOffset + 1); // Sector 0/block 0 is the UID so go straight to block 1 for the payload
                tagId = System.Text.Encoding.ASCII.GetString(block);
                if (tagId.Length == 1 && tagId[0] == 0x04)
                    // Ignore if ReadBlock returns a single byte 0x04, which appears to happen if there's a delay between the tag discovery and ReadBlock (e.g. running in the debugger) and we don't want to treat it as a conventional tag by acciden
                    tagId = string.Empty;
                else if (tagId.Length > 0 && tagId.Contains('\0')) 
                    tagId = tagId.Substring(0, tagId.IndexOf('\0'));
            } else {
                Console.WriteLine(
quot;Mifare Classic tag authentication failure: {sUid}");
            }
        }
        catch (Exception ex) {
            Console.WriteLine(
quot;Mifare Classic tag read exception: {ex.Message}");
        }
        finally {
            if (mfc != null && mfc.IsConnected)
                mfc.Close();
            if (tagId != string.Empty)
                Console.WriteLine(
quot;Mifare Classic tag found: {sUid} {tagId}");
        }
    }
    if (tagId != string.Empty)
        Do stuff
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

楠木可依 2025-01-30 21:58:37

当手机不支持它并且不会修复所有设备时,这看起来是一种超级骇人听闻的方式,可以尝试启用Mifare Classic支持。

But your problem is the hack relies on modifying the Tag Object that your App has created from the Intent when you are using the

,在使用较新且更好的enableReaderDermode api时(因为您使用的是方法ontagdiscovered),该)直接给出标签对象。

我没有经过Android代码来解决所有这些问题,但我的猜测是它是共享内存对象的某种形式,但它被定义为“单向”回调。

因此,由于您的应用程序不是tag对象的创建者,因此您没有能力修改它。

因此,此hack可能只有在您使用旧启用foreforegroundispatch的情况下才能起作用,在您自己的应用中删除包裹的对象(tag tag = intent.getParcelableableExtra(nfcadapter.extra_tag); <</code>)并可以完全访问标签对象,因为您的过程创建了它。

使用Mifare Classic Tool应用程序后,您的代码之所以能够工作的原因是,一旦标记硬件已进行身份验证,它将保持在“身份验证”状态下,直到将其从RF字段中删除并失去电源为止。

That looks a super hacky way of trying to enable Mifare Classic support when the phone does not support it and it won't fix all devices.

But your problem is the hack relies on modifying the Tag Object that your App has created from the Intent when you are using the old API enableForegrounDispatch

This old API has some other issues, where as you are using the newer and better enableReaderMode API (because you are using the method OnTagDiscovered) which gets directly give the Tag Object.

I've not been through the Android code to work all this out but my guess is that it is some form of shared memory object, it is though defined as a "oneway" callback.

Thus as your App process is not the creator of the Tag object you don't have the ability to modify it.

So this hack will probably only work if you are using the old enableForegrounDispatch where you de-Parcel the Parcelled object in your own App ( Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); ) and have full access to Tag object because your process created it.

The reason why your code works after using Mifare Classic Tool App is that once the Tag Hardware has been authenticated, it stays in the "authenticated" state until it is removed from the RF field and it looses power.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文