|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace POSV.Utils
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// M1卡功能类
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class MifareCardUtils
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
private static byte[] KEY_A = { 0x6F, 0x82, 0xD7, 0x20, 0xD9, 0x4B };
|
|
|
|
|
|
|
|
|
|
private static byte[] KEY_Other = { 0x46 , 0x46 , 0x46 , 0x46 , 0x46 , 0x46 };
|
|
|
|
|
|
|
|
|
|
private static string PASSWD = "AE302A12B644A790A22E53F13BCC4AB8";
|
|
|
|
|
|
|
|
|
|
public static int Init(Int16 port , int baud)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32_Init(port , baud);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Status(int handle)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32_Status(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Beep(int handle , int msec)
|
|
|
|
|
{
|
|
|
|
|
Mwrf32_Beep(handle , msec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Tuple<int , string> Card(int handle)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32_Card(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Tuple<int , string> Read(int handle , int mode , int sector , int block)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32_Read(handle , mode , sector , block);
|
|
|
|
|
}
|
|
|
|
|
public static Tuple<int, string> Read_Other(int handle, int mode, int sector, int block)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32_Read_Other(handle, mode, sector, block);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Halt(int handle)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32_Halt(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Exit(int handle)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32_Exit(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取卡片序列号
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="handle"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static string GetSnr(int handle)
|
|
|
|
|
{
|
|
|
|
|
byte[] snr = new byte[5];
|
|
|
|
|
//开始寻卡,0——表示IDLE模式,一次只对一张卡操作
|
|
|
|
|
int status = Mwrf32.rf_card(handle, 1, snr);
|
|
|
|
|
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info(ByteArrayToHexString(snr));
|
|
|
|
|
return ByteArrayToHexString(snr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 明华RF-EYE-U010-MEM 读卡器初始化
|
|
|
|
|
/// 型号:RF-EYE-U010-MEM
|
|
|
|
|
/// 批号:12520169920
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private static int Mwrf32_Init(Int16 port , int baud)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32.rf_init(port , baud);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 取得硬件版本号
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="handle"></param>
|
|
|
|
|
/// <param name="state"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private static int Mwrf32_Status(int handle)
|
|
|
|
|
{
|
|
|
|
|
byte[] version = new byte[30];
|
|
|
|
|
|
|
|
|
|
return Mwrf32.rf_get_status(handle , version);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 蜂鸣
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="handle"></param>
|
|
|
|
|
/// <param name="msec"></param>
|
|
|
|
|
private static void Mwrf32_Beep(int handle , int msec)
|
|
|
|
|
{
|
|
|
|
|
Mwrf32.rf_beep(handle , msec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Tuple<int , string> Mwrf32_Card(int handle)
|
|
|
|
|
{
|
|
|
|
|
byte[] snr = new byte[5];
|
|
|
|
|
//开始寻卡,0——表示IDLE模式,一次只对一张卡操作
|
|
|
|
|
int status = Mwrf32.rf_card(handle , 1 , snr);
|
|
|
|
|
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
byte[] snr1 = new byte[8];
|
|
|
|
|
Mwrf32.hex_a(snr , snr1 , 4);
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Debug("检测到会员卡:" + System.Text.Encoding.Default.GetString(snr1));
|
|
|
|
|
|
|
|
|
|
return new Tuple<int, string>(status, System.Text.Encoding.Default.GetString(snr1));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<int , string>(status , string.Empty);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static Tuple<int, string> Mwrf32_Read(int handle , int mode , int sector , int block)
|
|
|
|
|
{
|
|
|
|
|
int status = Mwrf32.rf_load_key(handle , mode , sector , KEY_A);
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
status = Mwrf32.rf_authentication(handle , 0 , sector); //验证密码
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
byte[] buffer = new byte[16];
|
|
|
|
|
|
|
|
|
|
status = Mwrf32.rf_read(handle , sector * 4 + block , buffer); //读数据
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
string _message = "";
|
|
|
|
|
for (int i = 0; i < 4 * 4; i++)
|
|
|
|
|
{
|
|
|
|
|
_message += buffer[i].ToString("X2");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AesParser parser = new AesParser();
|
|
|
|
|
byte[] key = parser.ParseKey(PASSWD);
|
|
|
|
|
int nK = PASSWD.Length / 8;
|
|
|
|
|
int nR = nK + 6;
|
|
|
|
|
byte[][] expandedKey = Aes.ExpandKey(key , nK);
|
|
|
|
|
|
|
|
|
|
byte[,] state = parser.ParseHexString(ByteArrayToHexString(buffer));
|
|
|
|
|
byte[][,] all = Aes.InvCipher(state , expandedKey , nR);
|
|
|
|
|
|
|
|
|
|
byte[,] cardNo = all[nR];
|
|
|
|
|
|
|
|
|
|
byte[] rst = new byte[4 * 4];
|
|
|
|
|
for (int row = 0; row < 4; row++)
|
|
|
|
|
{
|
|
|
|
|
for (int col = 0; col < 4; col++)
|
|
|
|
|
{
|
|
|
|
|
rst[(row * 4) + col] = cardNo[row , col];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new Tuple<int , string>(status , new String(new ASCIIEncoding().GetChars(rst)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Debug("读取卡数据失败!" , sector);
|
|
|
|
|
return new Tuple<int , string>(status , string.Empty);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Debug("验证{0}扇区密码失败!" , sector);
|
|
|
|
|
return new Tuple<int , string>(status , string.Empty);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Debug("加载密钥失败!");
|
|
|
|
|
return new Tuple<int , string>(status , string.Empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static Tuple<int, string> Mwrf32_Read_Other(int handle, int mode, int sector, int block)
|
|
|
|
|
{
|
|
|
|
|
int status = Mwrf32.rf_load_key(handle, mode, sector, KEY_Other);
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
status = Mwrf32.rf_authentication(handle, 0, sector); //验证密码
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
byte[] buffer = new byte[16];
|
|
|
|
|
|
|
|
|
|
status = Mwrf32.rf_read(handle, sector * 4 + block, buffer); //读数据
|
|
|
|
|
if (status == 0)
|
|
|
|
|
{
|
|
|
|
|
string _message = "";
|
|
|
|
|
for (int i = 0; i < 4 * 4; i++)
|
|
|
|
|
{
|
|
|
|
|
_message += buffer[i].ToString("X2");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var array = HexStringToByteArray(_message.ToLower().Substring(0, 16));
|
|
|
|
|
|
|
|
|
|
string hex = System.Text.Encoding.Default.GetString(array).Replace("\0", " ").Trim();
|
|
|
|
|
Console.WriteLine(hex);
|
|
|
|
|
|
|
|
|
|
string str = decode(hex);
|
|
|
|
|
Console.WriteLine(str);
|
|
|
|
|
|
|
|
|
|
return new Tuple<int, string>(status, str);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Debug("读取卡数据失败!", sector);
|
|
|
|
|
return new Tuple<int, string>(status, string.Empty);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Debug("验证{0}扇区密码失败!", sector);
|
|
|
|
|
return new Tuple<int, string>(status, string.Empty);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Debug("加载密钥失败!");
|
|
|
|
|
return new Tuple<int, string>(status, string.Empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static string decode(string encryptStr)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//------------解密--------------
|
|
|
|
|
// 加密串
|
|
|
|
|
encryptStr = encryptStr.Trim();
|
|
|
|
|
int length = encryptStr.Length;
|
|
|
|
|
string result = "";
|
|
|
|
|
for (int i = 1; i <= length; i++)
|
|
|
|
|
{
|
|
|
|
|
result += chr(ord(encryptStr[i - 1].ToString()) - (length - i - 2) * 2);
|
|
|
|
|
}
|
|
|
|
|
// 字符反转
|
|
|
|
|
char[] arr = result.ToCharArray();
|
|
|
|
|
Array.Reverse(arr);
|
|
|
|
|
result = new string(arr);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(e.ToString());
|
|
|
|
|
Console.Write(e.StackTrace);
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int ord(string s)
|
|
|
|
|
{
|
|
|
|
|
return (int)s[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string chr(int i)
|
|
|
|
|
{
|
|
|
|
|
StringBuilder sbu = new StringBuilder();
|
|
|
|
|
sbu.Append((char)i);
|
|
|
|
|
return sbu.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int Mwrf32_Halt(int handle)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32.rf_halt(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="handle"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private static int Mwrf32_Exit(int handle)
|
|
|
|
|
{
|
|
|
|
|
return Mwrf32.rf_exit(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 字节数组转十六进制字符串
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private static string ByteArrayToHexString(byte[] data)
|
|
|
|
|
{
|
|
|
|
|
StringBuilder sb = new StringBuilder(data.Length * 3);
|
|
|
|
|
foreach (byte b in data)
|
|
|
|
|
{
|
|
|
|
|
sb.Append(Convert.ToString(b , 16).PadLeft(2 , '0'));
|
|
|
|
|
}
|
|
|
|
|
return sb.ToString().ToUpper();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static byte[] HexStringToByteArray(string s)
|
|
|
|
|
{
|
|
|
|
|
s = s.Replace(" " , "");
|
|
|
|
|
byte[] buffer = new byte[s.Length / 2];
|
|
|
|
|
for (int i = 0; i < s.Length; i += 2)
|
|
|
|
|
{
|
|
|
|
|
buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i , 2) , 16);
|
|
|
|
|
}
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|