使用ACR122U NFC读卡器对M1卡进行读写操作(可以读写中文)

时间:2024-09-09 11:05:32

因为项目需要,第一次接触到了ACR122U NFC读卡器(非接触式)和M1卡,首先介绍一下想要读写应该知道的基本知识。

我就根据我的理解先叙述一下:

ACR122U 是一款连机非接触式智能卡读写器,可以读写 ISO 14443-4 A 类和 B 类卡、MIFARE®卡、
ISO18092 卡以及 FeliCa 标签。由于符合 PC/SC 标准,它可以与现有的 PC/SC 应用相兼容。
作为非接触式标签与个人电脑的中间设备,ACR122U 通过 USB 端口与电脑建立连接并执行电脑发出
的指令,从而实现与非接触式标签的通信或者对外围设备(LED 指示灯或蜂鸣器)进行控制。

具体M1卡的介绍,推荐链接:https://blog.****.net/woniu3/article/details/51324483

M1卡里面有16(0-15)个扇区,每个扇区包含4个块,0扇区是0-3区块,1扇区是4-7区块,,,以此类推,15扇区就是60-63。

(1)其中0扇区里的0区块存储的是厂商代码,已经固化,不可更改。

(2)每个扇区的块0(除0扇区外)、块1、块2 为数据块,可用于存贮数据。数据块可作两种应用: 
用作一般的数据保存,可以进行读、写操作。 
用作数据值,可以进行初始化值、加值、减值、读值操作。

(3)每个扇区的块3 为控制块,包括了密码A、存取控制、密码B。

使用ACR122U NFC读卡器对M1卡进行读写操作(可以读写中文)

这个图是用破解工具读取出来的M1卡的数据。存储的是16进制的数据。

使用ACR122U NFC读卡器对M1卡进行读写操作(可以读写中文)

这是我做的页面

使用ACR122U NFC读卡器对M1卡进行读写操作(可以读写中文)

这是窗体的代码

 using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms; namespace WindowsFormsApplication1
{
public partial class NFCCardForm : Form
{
public NFCCardForm()
{
InitializeComponent();
} #region 全局变量声明
public int retCode, hContext, hCard, Protocol, ReaderCount, nBytesRet, blockCount, blockNum, ShanQuNum, yuShu;
public bool connActive = false;
public byte[] SendBuff = new byte[];//最多可以放752个
public byte[] RecvBuff = new byte[];
public byte[] SendBuffAll = new byte[];//全部
public byte[] RecvBuffAll = new byte[];
public byte[] bytes = new byte[];
public int SendLen, RecvLen, ReaderLen, ATRLen, dwState, dwActProtocol;
public int reqType, Aprotocol, dwProtocol, cbPciLength;
public ModWinsCard.SCARD_IO_REQUEST pioSendRequest;
string readStr = "";
public static string writeStr = "";
bool isReadAll = false;
#endregion #region 窗体事件
private void Form1_Load(object sender, EventArgs e)
{
InitMenu();
} /// <summary>
/// 读卡器初始化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bInit_Click(object sender, EventArgs e)
{
string ReaderList = "" + Convert.ToChar();
int indx;
int pcchReaders = ;
string rName = ""; //Establish Context
retCode = ModWinsCard.SCardEstablishContext(ModWinsCard.SCARD_SCOPE_USER, , , ref hContext); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
displayOut(, retCode, "");
return;
} // 2. List PC/SC card readers installed in the system retCode = ModWinsCard.SCardListReaders(this.hContext, null, null, ref pcchReaders); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
displayOut(, retCode, "");
return;
}
EnableButtons();
byte[] ReadersList = new byte[pcchReaders];
// Fill reader list
retCode = ModWinsCard.SCardListReaders(this.hContext, null, ReadersList, ref pcchReaders);
if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
mMsg.AppendText("SCardListReaders Error: " + ModWinsCard.GetScardErrMsg(retCode));
return;
}
else
{
displayOut(, , " ");
} rName = "";
indx = ; //Convert reader buffer to string
while (ReadersList[indx] != )
{
while (ReadersList[indx] != )
{
rName = rName + (char)ReadersList[indx];
indx = indx + ;
}
//Add reader name to list
cbReader.Items.Add(rName);
rName = "";
indx = indx + ;
} if (cbReader.Items.Count > )
{
cbReader.SelectedIndex = ;
}
} private void bConnect_Click(object sender, EventArgs e)
{
retCode = ModWinsCard.SCardConnect(hContext, cbReader.SelectedItem.ToString(), ModWinsCard.SCARD_SHARE_SHARED,
ModWinsCard.SCARD_PROTOCOL_T1, ref hCard, ref Protocol); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
retCode = ModWinsCard.SCardConnect(hContext, cbReader.SelectedItem.ToString(), ModWinsCard.SCARD_SHARE_DIRECT,
, ref hCard, ref Protocol);
if (retCode != ModWinsCard.SCARD_S_SUCCESS)
displayOut(, retCode, "");
else
{
displayOut(, , "成功连接到" + cbReader.Text);//Successful connection to
}
}
else
{
displayOut(, , "成功连接到" + cbReader.Text);
}
GetUID();
connActive = true;
gbLoadKeys.Enabled = true;
gbAuth.Enabled = true;
gbBinOps.Enabled = true;
groupBox1.Enabled = true;
tKeyNum.Focus();
rbKType1.Checked = true;
btnClear.Enabled = true;
btnRead.Enabled = true;
btnWrite.Enabled = true;
} private void bClear_Click(object sender, EventArgs e)
{
mMsg.Clear();
} private void bReset_Click(object sender, EventArgs e)
{
if (connActive)
{
retCode = ModWinsCard.SCardDisconnect(hCard, ModWinsCard.SCARD_UNPOWER_CARD);
} retCode = ModWinsCard.SCardReleaseContext(hCard);
InitMenu();
} private void bQuit_Click(object sender, EventArgs e)
{
// terminate the application
retCode = ModWinsCard.SCardReleaseContext(hContext);
retCode = ModWinsCard.SCardDisconnect(hCard, ModWinsCard.SCARD_UNPOWER_CARD);
System.Environment.Exit();
} private void bLoadKey_Click(object sender, EventArgs e)
{
byte tmpLong;
string tmpStr; if (tKey1.Text == "" | !byte.TryParse(tKey1.Text, System.Globalization.NumberStyles.HexNumber, null, out tmpLong))
{
tKey1.Focus();
tKey1.Text = "";
return;
} if (tKey2.Text == "" | !byte.TryParse(tKey2.Text, System.Globalization.NumberStyles.HexNumber, null, out tmpLong))
{
tKey2.Focus();
tKey2.Text = "";
return;
} if (tKey3.Text == "" | !byte.TryParse(tKey3.Text, System.Globalization.NumberStyles.HexNumber, null, out tmpLong))
{
tKey3.Focus();
tKey3.Text = "";
return;
} if (tKey4.Text == "" | !byte.TryParse(tKey4.Text, System.Globalization.NumberStyles.HexNumber, null, out tmpLong))
{
tKey4.Focus();
tKey4.Text = "";
return;
} if (tKey5.Text == "" | !byte.TryParse(tKey5.Text, System.Globalization.NumberStyles.HexNumber, null, out tmpLong))
{
tKey5.Focus();
tKey5.Text = "";
return;
} if (tKey6.Text == "" | !byte.TryParse(tKey6.Text, System.Globalization.NumberStyles.HexNumber, null, out tmpLong))
{
tKey6.Focus();
tKey6.Text = "";
return;
} ClearBuffers();
// Load Authentication Keys command
SendBuff[] = 0xFF; // Class
SendBuff[] = 0x82; // INS
SendBuff[] = 0x00; // P1 : Key Structure
SendBuff[] = byte.Parse(tKeyNum.Text, System.Globalization.NumberStyles.HexNumber);
SendBuff[] = 0x06; // P3 : Lc
SendBuff[] = byte.Parse(tKey1.Text, System.Globalization.NumberStyles.HexNumber); // Key 1 value
SendBuff[] = byte.Parse(tKey2.Text, System.Globalization.NumberStyles.HexNumber); // Key 2 value
SendBuff[] = byte.Parse(tKey3.Text, System.Globalization.NumberStyles.HexNumber); // Key 3 value
SendBuff[] = byte.Parse(tKey4.Text, System.Globalization.NumberStyles.HexNumber); // Key 4 value
SendBuff[] = byte.Parse(tKey5.Text, System.Globalization.NumberStyles.HexNumber); // Key 5 value
SendBuff[] = byte.Parse(tKey6.Text, System.Globalization.NumberStyles.HexNumber); // Key 6 value SendLen = ;
RecvLen = ; retCode = SendAPDU(, false, ); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return;
}
else
{
tmpStr = "";
for (int indx = RecvLen - ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
if (tmpStr.Trim() != "90 00")
{
displayOut(, , "载入密钥失败!");//Load authentication keys error
}
} private void btnAuth_Click(object sender, EventArgs e)
{
int tempInt, indx;
byte tmpLong;
string tmpStr; // Validate input
if (tBlkNo.Text == "" | !int.TryParse(tBlkNo.Text, out tempInt))
{
tBlkNo.Focus();
tBlkNo.Text = "";
return;
} if (int.Parse(tBlkNo.Text) > )
{
tBlkNo.Text = "";
} if (tAuthenKeyNum.Text == "" | !byte.TryParse(tAuthenKeyNum.Text, System.Globalization.NumberStyles.HexNumber, null, out tmpLong))
{
tAuthenKeyNum.Focus();
tAuthenKeyNum.Text = "";
return;
}
else if (int.Parse(tAuthenKeyNum.Text) > )
{
tAuthenKeyNum.Text = "";
return;
} ClearBuffers(); SendBuff[] = 0xFF; // Class
SendBuff[] = 0x86; // INS
SendBuff[] = 0x00; // P1
SendBuff[] = 0x00; // P2
SendBuff[] = 0x05; // Lc
SendBuff[] = 0x01; // Byte 1 : Version number
SendBuff[] = 0x00; // Byte 2
SendBuff[] = (byte)int.Parse(tBlkNo.Text); // Byte 3 : Block number if (rbKType1.Checked == true)
{
SendBuff[] = 0x60;
}
else if (rbKType2.Checked == true)
{
SendBuff[] = 0x61;
} SendBuff[] = byte.Parse(tAuthenKeyNum.Text, System.Globalization.NumberStyles.HexNumber); // Key 5 value SendLen = ;
RecvLen = ; retCode = SendAPDU(, false, ); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return;
}
else
{
tmpStr = "";
for (indx = ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
if (tmpStr.Trim() == "90 00")
{
displayOut(, , "验证成功!");//Authentication success
}
else
{
displayOut(, , "验证失败!");//Authentication failed
}
} private void bBinRead_Click(object sender, EventArgs e)
{
string tmpStr;
int indx; // Validate Inputs
tBinData.Text = ""; if (tBinBlk.Text == "")
{
tBinBlk.Focus();
return;
} if (int.Parse(tBinBlk.Text) > )
{
tBinBlk.Text = "";
return;
} if (tBinLen.Text == "")
{
tBinLen.Focus();
return;
} ClearBuffers();
SendBuff[] = 0xFF;
SendBuff[] = 0xB0;
SendBuff[] = 0x00;
SendBuff[] = (byte)int.Parse(tBinBlk.Text);
SendBuff[] = (byte)int.Parse(tBinLen.Text); SendLen = ;
RecvLen = SendBuff[] + ; retCode = SendAPDU(, false, ); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return;
}
else
{
tmpStr = "";
for (indx = RecvLen - ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
if (tmpStr.Trim() == "90 00")
{
tmpStr = "";
tmpStr = System.Text.Encoding.Default.GetString(RecvBuff);
byte[] c = new byte[];
if (tmpStr.Contains('?'))
{
if (IsBase64String(tmpStr.Split('?')[]))
{
c = Convert.FromBase64String(tmpStr.Split('?')[]);
tmpStr = System.Text.Encoding.Default.GetString(c);
}
}
else
{
if (IsBase64String(tmpStr))
{
c = Convert.FromBase64String(tmpStr);
tmpStr = System.Text.Encoding.Default.GetString(c);
}
}
tBinData.Text = tmpStr;
displayOut(, , tmpStr);
}
else
{
displayOut(, , "读取块失败!");//Read block error
}
} private void bBinUpd_Click(object sender, EventArgs e)
{
string tmpStr;
int indx, tempInt; if (tBinBlk.Text == "" | !int.TryParse(tBinBlk.Text, out tempInt))
{
tBinBlk.Focus();
tBinBlk.Text = "";
return;
} if (int.Parse(tBinBlk.Text) > )
{
tBinBlk.Text = "";
return;
} if (tBinLen.Text == "" | !int.TryParse(tBinLen.Text, out tempInt))
{
tBinLen.Focus();
tBinLen.Text = "";
return;
} if (tBinData.Text == "")
{
tBinData.Focus();
return;
} tmpStr = tBinData.Text;
byte[] b = System.Text.Encoding.Default.GetBytes(tmpStr);
//转成 Base64 形式的 System.String
tmpStr = Convert.ToBase64String(b);
//将base64转成字符数组然后写入卡中
bytes = System.Text.Encoding.Default.GetBytes(tmpStr);
if (bytes.Length > )
{
MessageBox.Show("写入的数据长度超过16,请重新输入");
return;
}
ClearBuffers();
SendBuff[] = 0xFF; // CLA
SendBuff[] = 0xD6; // INS
SendBuff[] = 0x00; // P1
SendBuff[] = (byte)int.Parse(tBinBlk.Text); // P2 : Starting Block No.
SendBuff[] = (byte)bytes.Length; //(byte)int.Parse(tBinLen.Text); // P3 : Data length for (indx = ; indx <= bytes.Length - ; indx++)
{
SendBuff[indx + ] = bytes[indx];
}
SendLen = SendBuff[] + ;//
RecvLen = 0x02; retCode = SendAPDU(, false, ); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return;
}
else
{
tmpStr = "";
for (indx = ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
if (tmpStr.Trim() == "90 00")
{
tBinData.Text = "";
}
else
{
displayOut(, , tmpStr.Trim());//""
}
} private void btnRead_Click(object sender, EventArgs e)
{
string readData = readStr;
AuthAllBootSector();
if (readStr == null)
return; if (IsBase64String(readStr.Split('?')[]))
{
byte[] c = Convert.FromBase64String(readStr);
readData = System.Text.Encoding.Default.GetString(c);
if (readData.Contains("结"))
readData = readData.Substring(, readData.IndexOf("结"));
}
readStr = null;
displayOut(, , readData); } private void btnWrite_Click(object sender, EventArgs e)
{
AuthAllBootSector();
blockCount = ;
} /// <summary>
/// 当文本框里的值发生改变时,动态显示出写入数据的长度
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tBinData_TextChanged(object sender, EventArgs e)
{
string tmpStr = tBinData.Text;
byte[] b = System.Text.Encoding.Default.GetBytes(tmpStr);
//转成 Base64 形式的 System.String
tmpStr = Convert.ToBase64String(b);
//将base64转成字节数组然后写入卡中
bytes = System.Text.Encoding.Default.GetBytes(tmpStr);
lblWriteLength.Text = bytes.Length.ToString();
} /// <summary>
/// 在写入新的内容时,先将卡里的原数据清空
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnClear_Click(object sender, EventArgs e)
{
int result;
for (int index = ; index <= ; index += )//验证
{
ClearBuffers();
SendBuff[] = 0xFF; // Class
SendBuff[] = 0x86; // INS
SendBuff[] = 0x00; // P1
SendBuff[] = 0x00; // P2
SendBuff[] = 0x05; // Lc
SendBuff[] = 0x01; // Byte 1 : Version number
SendBuff[] = 0x00; // Byte 2
SendBuff[] = (byte)index;//区块 // Byte 3 : Block number result = PartAuthBlock(, index);
if (result == )
break;
}
}
#endregion #region 自定义方法
private void InitMenu()
{
connActive = false;
cbReader.Text = "";
cbReader.Items.Clear();
mMsg.Text = "";
tKeyNum.SelectedIndex = ;
tAuthenKeyNum.SelectedIndex = ;
bInit.Enabled = true;
bConnect.Enabled = false;
bClear.Enabled = false;
displayOut(, , "程序准备就绪");//Program ready
bReset.Enabled = false;
gbLoadKeys.Enabled = false;
gbAuth.Enabled = false;
gbBinOps.Enabled = false;
groupBox1.Enabled = false;
btnClear.Enabled = false;
btnRead.Enabled = false;
btnWrite.Enabled = false;
} private void displayOut(int errType, int retVal, string PrintText)
{
switch (errType)
{
case :
mMsg.SelectionColor = Color.Green;
break;
case :
mMsg.SelectionColor = Color.Red;
PrintText = ModWinsCard.GetScardErrMsg(retVal);
break;
case :
mMsg.SelectionColor = Color.Black;
PrintText = "<" + PrintText;
break;
case :
mMsg.SelectionColor = Color.Black;
PrintText = ">" + PrintText;
break;
case :
break;
}
mMsg.AppendText(PrintText);
mMsg.AppendText("\n");
mMsg.SelectionColor = Color.Black;
mMsg.Focus();
} private void EnableButtons()
{
bInit.Enabled = false;
bConnect.Enabled = true;
bClear.Enabled = true;
bReset.Enabled = true;
} private void ClearBuffers()
{
long indx; for (indx = ; indx <= ; indx++)
{
RecvBuff[indx] = ;
SendBuff[indx] = ;
RecvBuffAll[indx] = ;
SendBuffAll[indx] = ;
}
} //private static byte[] StringToByteSequence(string sourceString)
//{
// int i = 0, n = 0;
// int j = (sourceString.Length) / 2; // byte[] a = new byte[j];
// for (i = 0, n = 0; n < j; i += 2, n++)
// {
// a[n] = Convert.ToByte(sourceString.Substring(i, 2), 16);
// }
// return a;
//} /// <summary>
///
/// </summary>
/// <param name="handleFlag">是否是更新操作</param>
/// <param name="isReadOrWriteAll">是不是全部读取或写入</param>
/// <returns></returns>
public int SendAPDU(int handleFlag, bool isReadOrWriteAll, int dataLength)
{
int indx;
string tmpStr; pioSendRequest.dwProtocol = Aprotocol;
pioSendRequest.cbPciLength = ; // Display Apdu In
tmpStr = "";
if (handleFlag == )//更新
{
if (isReadOrWriteAll)
{
for (indx = ; indx <= ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", SendBuffAll[indx]);//更新的APDU命令
}
for (int i = ; i <= SendLen - ; i++)
{
SendBuffAll[i + ] = bytes[i + dataLength];
}
SendLen = ;
}
else
{
for (indx = ; indx <= ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", SendBuff[indx]);//更新的APDU命令
}
for (int i = ; i <= SendLen - ; i++)
{
SendBuff[i + ] = bytes[i];
}
}
}
else if (handleFlag == )//读取
{
if (isReadOrWriteAll)//全部
{
for (indx = ; indx <= SendLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", SendBuffAll[indx]);
}
}
else
{
for (indx = ; indx <= SendLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", SendBuff[indx]);
}
}
}
else if (handleFlag == )//清空
{
for (indx = ; indx <= ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", SendBuffAll[indx]);//更新的APDU命令
}
for (int i = ; i <= SendLen - ; i++)
{
SendBuffAll[i + ] = 0x00;
}
} displayOut(, , tmpStr);
if (!isReadOrWriteAll)
retCode = ModWinsCard.SCardTransmit(hCard, ref pioSendRequest, ref SendBuff[], SendLen, ref pioSendRequest, ref RecvBuff[], ref RecvLen);
else
retCode = ModWinsCard.SCardTransmit(hCard, ref pioSendRequest, ref SendBuffAll[], SendLen, ref pioSendRequest, ref RecvBuffAll[], ref RecvLen); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
displayOut(, retCode, "");
return retCode;
} tmpStr = "";
if (isReadOrWriteAll)
{
for (indx = ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuffAll[indx]);
}
}
else
{
for (indx = ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
displayOut(, , tmpStr);
return retCode;
} #region GetUID()
/// <summary>
/// 获取UID
/// </summary>
private void GetUID()
{
// Get the firmaware version of the reader
string tmpStr;
int intIndx;
ClearBuffers(); #region GetFirmware APDU
//SendBuff[0] = 0xFF;
//SendBuff[1] = 0x00;
//SendBuff[2] = 0x48;
//SendBuff[3] = 0x00;
//SendBuff[4] = 0x00;
//SendLen = 5;
//RecvLen = 10;
#endregion SendBuff[] = 0xFF;
SendBuff[] = 0xCA;
SendBuff[] = 0x00;
SendBuff[] = 0x00;
SendBuff[] = 0x00;
SendLen = ;
RecvLen = ;
retCode = SendAPDU(, false, );
if (retCode != ModWinsCard.SCARD_S_SUCCESS)
return; // Interpret firmware data
//tmpStr = "Firmware Version(版本): ";
tmpStr = "UID: ";
for (intIndx = ; intIndx <= RecvLen - ; intIndx++)
{
tmpStr = tmpStr + string.Format("{0:X2}", RecvBuff[intIndx]);
}
displayOut(, , tmpStr);
}
#endregion /// <summary>
/// 验证所有区块
/// </summary>
/// <param name="handleFlag">处理操作的标志handleFlag 0清空,1读取,2写入</param>
private void AuthAllBootSector(int handleFlag)
{
int result; if (handleFlag == )
{
string data = writeStr;//获取要写入的字符串
byte[] b = System.Text.Encoding.Default.GetBytes(data);
//转成 Base64 形式的 System.String
data = Convert.ToBase64String(b);
bytes = System.Text.Encoding.Default.GetBytes(data);
if (bytes.Length % != )
{
b = null;
string endSign = "结结结结结结结";
//for (int i = 0; i < (bytes.Length % 16); i++)
//{
//endSign = "结结结结结结结"; //写入的数据不够填充满16位,最后的base64容易混乱,所以加个汉字,填满16位
//}
string str = writeStr + endSign;
b = System.Text.Encoding.Default.GetBytes(str);
data = "";
data = Convert.ToBase64String(b);
} //将base64转成16进制然后写入卡中
bytes = System.Text.Encoding.Default.GetBytes(data);
//写入的数据需要的区块数量
blockNum = (bytes.Length % == ? (bytes.Length / ) : (bytes.Length / + ));
//需要验证的扇区的数量,把有两个数据块的0扇区加上
ShanQuNum = (blockNum - ) % == ? (blockNum - ) / + : (blockNum - ) / + ;
//获取最后一个扇区的写入的块的数量,yushu==0,则正好写满当前验证块(3块数据块);
//yushu==1,则写入当前验证块;yushu==2,则写入当前验证块+1
yuShu = (blockNum - ) % ;
for (int i = ; i < * ShanQuNum; i += ) //验证 块
{
ClearBuffers();
SendBuff[] = 0xFF; // Class
SendBuff[] = 0x86; // INS
SendBuff[] = 0x00; // P1
SendBuff[] = 0x00; // P2
SendBuff[] = 0x05; // Lc
SendBuff[] = 0x01; // Byte 1 : Version number
SendBuff[] = 0x00; // Byte 2
SendBuff[] = (byte)i; // Byte 3 : Block number result = PartAuthBlock(handleFlag, i);
if (result == )
break;
}
}
else if (handleFlag == )
{
for (int index = ; index <= ; index += )//验证
{
ClearBuffers();
SendBuff[] = 0xFF; // Class
SendBuff[] = 0x86; // INS
SendBuff[] = 0x00; // P1
SendBuff[] = 0x00; // P2
SendBuff[] = 0x05; // Lc
SendBuff[] = 0x01; // Byte 1 : Version number
SendBuff[] = 0x00; // Byte 2
SendBuff[] = (byte)index;//块 // Byte 3 : Block number result = PartAuthBlock(handleFlag, index);
if (result == )
break;
}
}
} /// <summary>
/// 在读取或写入操作前需要验证区块
/// </summary>
/// <param name="handleFlag">是否为写入、更新操作</param>
/// <param name="index">验证的区块号</param>
/// <returns></returns>
private int PartAuthBlock(int handleFlag, int index)
{
int indx;
string tmpStr;
if (rbKType1.Checked == true)
{
SendBuff[] = 0x60;//keyA
}
else if (rbKType2.Checked == true)
{
SendBuff[] = 0x61;//keyB
} SendBuff[] = byte.Parse(tAuthenKeyNum.Text, System.Globalization.NumberStyles.HexNumber); // Key 5 value SendLen = ;
RecvLen = ; retCode = SendAPDU(, false, ); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return ;
}
else
{
tmpStr = "";
for (indx = ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
if (tmpStr.Trim() == "90 00")
{
displayOut(, , "验证成功!");//Authentication success
if (handleFlag == )//清空
{
if (index == )
{
index += ;//从块1开始写入
for (int i = index; i <= ; i++)
{
AllBlockClear(i);
}
}
else
{
for (int i = index; i <= index + ; i++)
{
AllBlockClear(i);
}
}
}
else if (handleFlag == )//读取
{
ReadAllBlock(index);
}
else if (handleFlag == )//写入
{
bool isLastBlock = false;
if (index == )
{
index += ;//从块1开始写入
if ((index + ) < blockNum)
{
for (int i = index; i <= index + ; i++)
{
AllBlockWrite(i, false);//这里写每个块的写入循环
}
}
else
{
for (int i = index; i <= blockNum; i++)
{
if (i == blockNum)
isLastBlock = true;
AllBlockWrite(i, isLastBlock);//这里写每个块的写入循环
}
}
}
else
{
int temp = yuShu == ? (ShanQuNum-) * : (ShanQuNum - ) * ;
if (index < (ShanQuNum - ) * )
{
for (int i = index; i < index + ; i++)
{
AllBlockWrite(i, false);//这里写每个块的写入循环
}
}
else
{
if (yuShu == && index == (ShanQuNum - ) * )
{
for (int i = index; i < index + ; i++)
{
if (i == index + )
isLastBlock = true;
AllBlockWrite(i, isLastBlock);//这里写每个块的写入循环
}
}
else
{
for (int i = index; i <= index + yuShu - ; i++)
{
if (i == index + yuShu - )
isLastBlock = true;
AllBlockWrite(i, isLastBlock);//这里写每个块的写入循环
}
}
}
}
}
return ;
}
else
{
displayOut(, , "验证失败!");//Authentication failed
return ;
}
} private void ReadAllBlock(int index)
{
string tmpStr;
int indx;
isReadAll = true;
for (int i = index; i < index + ; i++)
{
ClearBuffers();
SendBuffAll[] = 0xFF;
SendBuffAll[] = 0xB0;
SendBuffAll[] = 0x00;
SendBuffAll[] = (byte)i;//块
SendBuffAll[] = (byte); SendLen = ;
RecvLen = SendBuffAll[] + ; retCode = SendAPDU(, true, ); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return;
}
else
{
tmpStr = "";
for (indx = RecvLen - ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuffAll[indx]);
}
}
if (tmpStr.Trim() == "90 00")
{
tmpStr = "";
tmpStr = System.Text.Encoding.Default.GetString(RecvBuffAll);
byte[] c = new byte[];
if (isReadAll)
{
if (tmpStr.Contains('?'))
{
if (IsBase64String(tmpStr.Split('?')[]))
{
c = Convert.FromBase64String(tmpStr.Split('?')[]);
readStr = readStr + tmpStr.Split('?')[];
}
}
//if (tmpStr.Contains('='))
//{
// string endStr = tmpStr.Split('=')[0] + "=";
// if (IsBase64String(endStr))
// {
// c = Convert.FromBase64String(endStr);
// readStr = readStr + endStr;
// }
// isReadAll = false;
//}
else
{
if (IsBase64String(tmpStr))
{
c = Convert.FromBase64String(tmpStr);
readStr = readStr + tmpStr.Split('?')[];
//tmpStr = System.Text.Encoding.Default.GetString(c);
}
}
}
displayOut(, , tmpStr);
}
else
{
displayOut(, , "读取块失败!");//Read block error
}
}
} /// <summary>
/// 验证读取出来的数据是否是Base64格式
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private bool IsBase64String(string s)
{
try { Convert.FromBase64String(s); }
catch { return false; }
return true;
} /// <summary>
/// 写入\更新所有区块
/// </summary>
/// <param name="index"></param>
/// <param name="isLastBlock"></param>
private void AllBlockWrite(int index, bool isLastBlock)
{
string tmpStr;
int indx, dataLength,leftBytes;
blockCount++; int blolen = bytes.Length % == ? (bytes.Length / ) : bytes.Length / + ;
leftBytes = bytes.Length % == ? : bytes.Length % ;
//int blockNum = (blolen - 2) % 3 == 0 ? (blolen - 2) / 3 : (blolen - 2) / 3 + 1;
ClearBuffers();
SendBuffAll[] = 0xFF; // CLA
SendBuffAll[] = 0xD6; // INS
SendBuffAll[] = 0x00; // P1
SendBuffAll[] = (byte)index; // P2 : Starting Block No.
if (isLastBlock)//最后一段要写入的数据
{
SendBuffAll[] = (byte); //(bytes.Length % 16) // P3 : Data length
dataLength = bytes.Length - leftBytes; //(blockCount - 1) * 16;
blockCount = ;
}
else
{
SendBuffAll[] = (byte); // P3 : Data length
//if (blockCount > blolen)
// blockCount = 0;
dataLength = index == ? : (blockCount - ) * ;
}
if (isLastBlock)
SendLen = leftBytes + ;
else
SendLen = SendBuffAll[] + ;//
RecvLen = 0x02; retCode = SendAPDU(, true, dataLength); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return;
}
else
{
tmpStr = "";
for (indx = ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuffAll[indx]);
}
}
if (tmpStr.Trim() == "90 00")
{
displayOut(, , "写入成功");
}
else
{
displayOut(, , "");
}
} private void AllBlockClear(int index)
{
string tmpStr;
int indx;
ClearBuffers();
SendBuffAll[] = 0xFF; // CLA
SendBuffAll[] = 0xD6; // INS
SendBuffAll[] = 0x00; // P1
SendBuffAll[] = (byte)index; // P2 : Starting Block No.
SendBuffAll[] = (byte); // P3 : Data length
SendLen = SendBuffAll[] + ;
RecvLen = 0x02; retCode = SendAPDU(, true, ); if (retCode != ModWinsCard.SCARD_S_SUCCESS)
{
return;
}
else
{
tmpStr = "";
for (indx = ; indx <= RecvLen - ; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuffAll[indx]);
}
}
if (tmpStr.Trim() == "90 00")
{
displayOut(, , "写入成功");
}
else
{
displayOut(, , "写卡失败");
}
} /// <summary>
/// 汉字转换到16进制
/// </summary>
/// <param name="s"></param>
/// <param name="charset">编码,如"gb2312","gb2312"</param>
/// <param name="fenge">是否每字符用空格分隔</param>
/// <returns></returns>
//public string ToHex(string s, string charset, bool fenge)
//{
// if ((s.Length % 2) != 0)
// {
// s += " ";//空格
// }
// System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
// byte[] bytes = chs.GetBytes(s);
// string str = "";
// for (int i = 0; i < bytes.Length; i++)
// {
// str += string.Format("{0:X}", bytes[i]);
// if (fenge && (i != bytes.Length - 1))
// {
// str += string.Format("{0}", " ");
// }
// }
// return str.ToUpper();
//} public byte[] ToHex(string s, string charset, bool fenge)
{
if ((s.Length % ) != )
{
s += " ";//空格
}
System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
byte[] bytes = chs.GetBytes(s);
//string str = "";
//for (int i = 0; i < bytes.Length; i++)
//{
// str += string.Format("{0:X}", bytes[i]);
// if (fenge && (i != bytes.Length - 1))
// {
// str += string.Format("{0}", " ");
// }
//}
return bytes;
} /// <summary>
/// 16进制转换成汉字
/// </summary>
/// <param name="hex"></param>
/// <param name="charset">编码,如"gb2312","gb2312"</param>
/// <returns></returns>
public string UnHex(string hex, string charset)
{
if (hex == null)
throw new ArgumentNullException("hex");
hex = hex.Replace(",", "");
hex = hex.Replace("/n", "");
hex = hex.Replace("//", "");
hex = hex.Replace(" ", "");
if (hex.Length % != )
{
hex += "";//空格
}
// 需要将 hex 转换成 byte 数组。
byte[] bytes = new byte[hex.Length / ]; for (int i = ; i < bytes.Length; i++)
{
try
{
// 每两个字符是一个 byte。
bytes[i] = byte.Parse(hex.Substring(i * , ),
System.Globalization.NumberStyles.HexNumber);
}
catch
{
// Rethrow an exception with custom message.
throw new ArgumentException("hex is not a valid hex number!", "hex");
}
}
System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
return chs.GetString(bytes);
}
#endregion
}
}

这个是可以写入中文的,思路大概是这样,先把中文转成base64,然后把base64格式的再转成byte[]。

完整的demo下载地址:https://github.com/wsn931203/DemoDataToNFCCard.git