草庐IT

C# 从 Mifare 卡读取 Ndef (Windows)

coder 2024-06-06 原文

我正在尝试通过 PcSc-Sharp 创建一个用于在 Mifare1K 卡上写入/读取的 c# 类.我得到了“ATR”数据,但我不知道如何从中生成 Ndef 消息。

我还调查了 Mifare -图书馆,但样本似乎有问题(无法在每个“卡附加事件”中读取扇区)。 所以我的问题是:有人知道 Windows 的工作方法/库,它可以为我做低级的事情吗?

编辑:我尝试了 PcSc 包中的 Mifare 样本。我无法加载 key :

using (var context = new SCardContext())
{
    context.Establish(SCardScope.System);
    var readerNames = context.GetReaders();
    if (readerNames == null || readerNames.Length < 1)
    {
        Console.WriteLine("You need at least one reader in order to run this example.");
        Console.ReadKey();
        return;
    }

    var readerName = ChooseReader(readerNames);
    if (readerName == null)
    {
        return;
    }

    using (var isoReader = new IsoReader(context, readerName, SCardShareMode.Shared, SCardProtocol.Any, false))
    {
        var card = new MifareCard(isoReader);
        var loadKeySuccessful = card.LoadKey(
            KeyStructure.NonVolatileMemory,
            0x00, // first key slot
            new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } // key
            );

        if (!loadKeySuccessful)
        {
            throw new Exception("LOAD KEY failed.");
        }
        // ... some more actions here ...
    }
}

有谁知道,如果loadKey参数没问题?

最佳答案

更新:我只能读取唯一的卡 ID,不能读取 NDef 标签。所以这是我的解决方案:

PcscWrapper.cs

internal class PcscWrapper : IDisposable
{
    private SCardMonitor pcscMonitor;
    private string lastUniqueId;
    private NfcEventType lastEventType;
    public string[] ReaderNames { get; private set; }

    internal event EventHandler<NfcEventArgs> PcScNfcEventReceived;

    internal bool CheckReaders()
    {
        using (var context = new SCardContext())
        {
            context.Establish(SCardScope.System);
            ReaderNames = context.GetReaders();                
            context.Release();
        }

        if (ReaderNames == null || ReaderNames.Length < 1)
        {
            Debug.WriteLine("PcscWrapper: No readers installed.");
            return false;
        }
        return true;
    }

    internal bool Initialize(out NfcDeviceType type)
    {
        type = NfcDeviceType.None;


        // Start Pcsc
        pcscMonitor = new SCardMonitor(ContextFactory.Instance, SCardScope.System);            
        pcscMonitor.MonitorException += (s, a) => OnPcScExceptionReceived(s, a);
        pcscMonitor.StatusChanged += (s, a) => OnPcScStatusChangeEventReceived(s, a);
        pcscMonitor.CardInserted += (s, a) => OnPcScCardStatusEventReceived(s, a);
        pcscMonitor.CardRemoved += (s, a) => OnPcScCardStatusEventReceived(s, a);

        foreach (var reader in ReaderNames)
        {
            Debug.WriteLine("PcscWrapper: Init Listening on reader " + reader + ".");
        }
        pcscMonitor.Start(ReaderNames);
        type = NfcDeviceType.Pcsc;
        return true;
    }

    private void OnPcScExceptionReceived(object s, PCSCException a)
    {
        var eventargs = new NfcEventArgs();
        eventargs.Type = NfcEventType.Unknown;            
        eventargs.Data = $"Error: {a.Message} ({a.SCardError.ToString()})";
        PcScNfcEventReceived?.Invoke(this, eventargs);
    }

    private void OnPcScStatusChangeEventReceived(object s, StatusChangeEventArgs a)
    {
        RaisePcScEvent(a.NewState, a.ReaderName);            
    }

    private void OnPcScCardStatusEventReceived(object s, CardStatusEventArgs a)
    {
        RaisePcScEvent(a.State, a.ReaderName);
    }

    private void RaisePcScEvent(SCRState state, string readerName)
    {
        bool doRaiseEvent = true;
        var eventargs = new NfcEventArgs();
        eventargs.ReaderName = readerName;
        eventargs.Data = $"New State for {readerName}: {state.ToString()}";
        switch (state)
        {
            case SCRState.Changed:
                eventargs.Type = NfcEventType.StatusChanged;
                break;
            case SCRState.Empty:
            case SCRState.Unavailable:
                eventargs.Type = NfcEventType.Disconnected;
                lastUniqueId = null;
                break;
            case SCRState.Present:
                eventargs.Type = NfcEventType.Connected;
                eventargs.UniqueCardID = state.CardIsPresent() ? GetUid(readerName) : null;
                if (eventargs.UniqueCardID == lastUniqueId)
                {
                    doRaiseEvent = false;
                }
                break;
            case SCRState.Unknown:
                eventargs.Type = NfcEventType.Unknown;
                break;
            default:
                doRaiseEvent = false;
                break;
        }
        if (doRaiseEvent && lastEventType != eventargs.Type)
        {
            string debugText = $"PcscWrapper: {eventargs.Type.ToString()} UID: ";
            debugText += eventargs.UniqueCardID ?? "N/A";
            Debug.WriteLine(debugText);
            System.Threading.Thread.Sleep(200);
            PcScNfcEventReceived?.Invoke(this, eventargs);
            lastUniqueId = eventargs.UniqueCardID;
            lastEventType = eventargs.Type;
        }
    }

    private string GetUid(string readerName)
    {
        using (var context = new SCardContext())
        {
            context.Establish(SCardScope.System);
            using (var rfidReader = new SCardReader(context))
            {
                var sc = rfidReader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any);
                if (sc != SCardError.Success)
                {
                    Debug.WriteLine($"PcscWrapper: Could not connect to reader {readerName}:\n{SCardHelper.StringifyError(sc)}");
                    return null;
                }

                var apdu = new CommandApdu(IsoCase.Case2Short, rfidReader.ActiveProtocol)
                {
                    CLA = 0xFF,
                    Instruction = InstructionCode.GetData,
                    P1 = 0x00,
                    P2 = 0x00,
                    Le = 0  // We don't know the ID tag size
                };

                sc = rfidReader.BeginTransaction();
                if (sc != SCardError.Success)
                {
                    Debug.WriteLine("PcscWrapper: Could not begin transaction.");
                    return null;
                }                    

                var receivePci = new SCardPCI(); // IO returned protocol control information.
                var sendPci = SCardPCI.GetPci(rfidReader.ActiveProtocol);

                var receiveBuffer = new byte[256];
                var command = apdu.ToArray();

                sc = rfidReader.Transmit(
                    sendPci,            // Protocol Control Information (T0, T1 or Raw)
                    command,            // command APDU
                    receivePci,         // returning Protocol Control Information
                    ref receiveBuffer); // data buffer

                if (sc != SCardError.Success)
                {
                    Debug.WriteLine("Error: " + SCardHelper.StringifyError(sc));
                }

                var responseApdu = new ResponseApdu(receiveBuffer, IsoCase.Case2Short, rfidReader.ActiveProtocol);
                rfidReader.EndTransaction(SCardReaderDisposition.Leave);
                rfidReader.Disconnect(SCardReaderDisposition.Reset);

                if (responseApdu.HasData)
                {
                    string uid = BitConverter.ToString(responseApdu.GetData()).Replace("-", "").ToUpper();
                    return (uid);
                }
            }
        }
        return null;
    }

    public void Dispose()
    {
        if (pcscMonitor != null)
        {
            if (pcscMonitor.Monitoring)
            {
                pcscMonitor.Cancel();
            }
            pcscMonitor.Dispose();
        }
    }
}

也许它对某人有用。

关于C# 从 Mifare 卡读取 Ndef (Windows),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34613840/

有关C# 从 Mifare 卡读取 Ndef (Windows)的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  6. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  7. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  8. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  9. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  10. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

随机推荐