Table of Contents

Class MifareCard

Namespace
Iot.Device.Card.Mifare
Assembly
Iot.Device.Mifare.dll

A Mifare card class Supports Mifare Classic 1K and 4K Also supports Mifare Plus 2K and 4K operating in SL1

public class MifareCard
Inheritance
MifareCard

Constructors

MifareCard(CardTransceiver, byte)

Constructor for Mifarecard

public MifareCard(CardTransceiver rfid, byte target)

Parameters

rfid CardTransceiver

A card transceiver class

target byte

The target number as some card readers attribute one

Properties

BlockNumber

The block number to authenticate or read or write

public byte BlockNumber { get; set; }

Property Value

byte

Capacity

The storage capacity

public MifareCardCapacity Capacity { get; set; }

Property Value

MifareCardCapacity

Command

The command to execute on the card

public MifareCardCommand Command { get; set; }

Property Value

MifareCardCommand

Data

The Data which has been read or to write for the specific block

public byte[] Data { get; set; }

Property Value

byte[]

DefaultBlocksNdefKeyA

Default block Key A for NDEF card

public static SpanByte DefaultBlocksNdefKeyA { get; }

Property Value

SpanByte

Remarks

DefaultFirstBlockNdefKeyA

Default Mifare Application Directory block Key A for NDEF card The MAD is in the first sector on all cards and also sector 16 on 2K and 4K cards

public static SpanByte DefaultFirstBlockNdefKeyA { get; }

Property Value

SpanByte

Remarks

DefaultKeyA

Default Key A

public static SpanByte DefaultKeyA { get; }

Property Value

SpanByte

DefaultKeyB

Default Key B

public static SpanByte DefaultKeyB { get; }

Property Value

SpanByte

KeyA

Key A Used for encryption/decryption

public byte[]? KeyA { get; set; }

Property Value

byte[]

KeyB

Key B Used for encryption/decryption

public byte[]? KeyB { get; set; }

Property Value

byte[]

SerialNumber

UUID is the Serial Number, called MAC sometimes

public byte[]? SerialNumber { get; set; }

Property Value

byte[]

Target

The tag number detected by the reader, only 1 or 2

public byte Target { get; set; }

Property Value

byte

Methods

BlockAccess(byte, byte[])

Get the block access information

public AccessType BlockAccess(byte blockNumber, byte[] sectorData)

Parameters

blockNumber byte

the block number

sectorData byte[]

the sector tailer data

Returns

AccessType

The access type rights

BlockNumberToBlockGroup(byte)

Determine the block group corresponding to a block number

public static byte BlockNumberToBlockGroup(byte blockNumber)

Parameters

blockNumber byte

block number

Returns

byte

block group

BlockNumberToSector(byte)

Determine the sector number corresponding to a particular block number

public static byte BlockNumberToSector(byte blockNumber)

Parameters

blockNumber byte

block number

Returns

byte

sector number

EncodeDefaultSectorAndBlockTailer()

Encode with default value the access sector and tailer blocks

public Triplet EncodeDefaultSectorAndBlockTailer()

Returns

Triplet

EncodeSectorAndBlockTailer(AccessSector, AccessType[])

Encode the desired access for the full sector including the block tailer

public Triplet EncodeSectorAndBlockTailer(AccessSector accessSector, AccessType[] accessTypes)

Parameters

accessSector AccessSector

The access desired

accessTypes AccessType[]

An array of 3 AccessType determining access of each block

Returns

Triplet

The 3 bytes encoding the rights

EncodeSectorAndClockTailer(AccessSector, AccessType[])

Encode the desired access for the full sector including the block tailer

[Obsolete("deprecated, use EncodeSectorAndBlockTailer instead")]
public Triplet EncodeSectorAndClockTailer(AccessSector accessSector, AccessType[] accessTypes)

Parameters

accessSector AccessSector

The access desired

accessTypes AccessType[]

An array of 3 AccessType determining access of each block

Returns

Triplet

The 3 bytes encoding the rights

EncodeSectorTailer(AccessSector)

Get the sector tailer bytes for a specific access sector configuration

public Triplet EncodeSectorTailer(AccessSector accessSector)

Parameters

accessSector AccessSector

the access sector

Returns

Triplet

the 3 bytes for configuration

EncodeSectorTailer(byte, AccessType)

Encode the sector tailer access type for a specific block

public Triplet EncodeSectorTailer(byte blockNumber, AccessType accessType)

Parameters

blockNumber byte

The block sector to encode

accessType AccessType

The access type to encode

Returns

Triplet

The encoded sector tailer for the specific block

EraseSector(SpanByte, SpanByte, byte, bool, bool)

Erase one sector

public bool EraseSector(SpanByte newKeyA, SpanByte newKeyB, byte sector, bool authenticateWithKeyA, bool resetAccessBytes)

Parameters

newKeyA SpanByte

The new key A, empty to use current one

newKeyB SpanByte

The new key B, empty to use current one

sector byte

The sector number. Refer to Mifare documentation to understand how blocks work especially for Mifare 2K and 4K

authenticateWithKeyA bool

True to authenticate with current Key A, false to authenticate with Key B

resetAccessBytes bool

True to reset all the access bytes

Returns

bool

True if success

Remarks

Sector 0 can't be fully erase, only the blocks 1 and 2 will be erased

FormatNdef(SpanByte)

Format the Card to NDEF

public bool FormatNdef(SpanByte keyB = default)

Parameters

keyB SpanByte

The key B to be used for formatting, if empty, will use the default key B

Returns

bool

True if success

Remarks

All sectors are configured as NFC Forum sectors

GetNumberBlocks()

Get the number of blocks for a specific sector

public int GetNumberBlocks()

Returns

int

The number of blocks for this specific sector

GetNumberBlocks(byte)

Get the number of blocks for a specific sector

public byte GetNumberBlocks(byte sectorNumber)

Parameters

sectorNumber byte

Input sector number

Returns

byte

The number of blocks for this specific sector

GetNumberSectors()

Get the number of sectors

public int GetNumberSectors()

Returns

int

IsFormattedNdef()

Check if the card formated to NDEF

public bool IsFormattedNdef()

Returns

bool

True if NDEF formatted

Remarks

It will only check the first 2 block of the first sector and that the GPB is set properly

IsSectorBlock(byte)

Is it a block sector?

public bool IsSectorBlock(byte blockNumber)

Parameters

blockNumber byte

Input block number

Returns

bool

True if it is a sector block

ReselectCard()

Select the card. Needed if authentication or read/write failed

public bool ReselectCard()

Returns

bool

True if success

RunMifareCardCommand()

Run the last setup command. In case of reading bytes, they are automatically pushed into the Data property

public int RunMifareCardCommand()

Returns

int

-1 if the process fails otherwise the number of bytes read

SectorTailerAccess(byte, byte[])

Get the sector tailer access information

public AccessSector SectorTailerAccess(byte blockNumber, byte[] sectorData)

Parameters

blockNumber byte

the block sector number

sectorData byte[]

The full sector data to decode

Returns

AccessSector

the access sector rights

SectorToBlockNumber(byte, byte)

Determine the first block number of a specified sector and block group

public static byte SectorToBlockNumber(byte sector, byte group = 0)

Parameters

sector byte

sector number

group byte

group (0 to 3, where 3 is the sector trailer)

Returns

byte

block number of the first (or only) block in the group

SetCapacity(ushort, byte)

From the ATQA ans SAK data find common card capacity

public void SetCapacity(ushort ATQA, byte SAK)

Parameters

ATQA ushort

The ATQA response

SAK byte

The SAK response

Remarks

Does not recognize Mifare Plus cards, capacity must be set manually

TryReadNdefMessage(out NdefMessage)

Try to read a NDEF Message from a Mifare card

public bool TryReadNdefMessage(out NdefMessage message)

Parameters

message NdefMessage

The NDEF message

Returns

bool

True if success

WriteDataBlock(byte)

Perform a write using the 16 bytes present in Data on a specific block

public bool WriteDataBlock(byte block)

Parameters

block byte

The block number to write

Returns

bool

True if success

Remarks

You will need to be authenticated properly before

WriteNdefMessage(NdefMessage, bool)

Write an NDEF Message

public bool WriteNdefMessage(NdefMessage message, bool writeKeyA = true)

Parameters

message NdefMessage

The NDEF Message to write

writeKeyA bool

True to write with Key A

Returns

bool

True if success