C#从Mifare卡读取Ndef(Windows)

时间:2016-01-05 14:19:06

标签: c# windows mifare ndef pcsc

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

我还调查了Mifare - 图书馆,但样本似乎是错误的(每个“附加卡事件”都无法读取扇区)。 所以我的问题是:有没有人知道Windows的工作方法/库,这对我来说是低级别的东西?

编辑:我尝试了PcSc包中的Mifare样本。在那里我无法加载密钥:

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参数没问题吗?

1 个答案:

答案 0 :(得分:0)

更新:我只能读取唯一的卡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();
        }
    }
}

也许它对某人有用。