ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C#】利用读卡器对IC卡进行读写、加密等操作,源码下载

2020-04-02 13:41:04  阅读:303  来源: 互联网

标签:sector string C# IC卡 扇区 源码 cardID new 255


本例应用场合:对IC卡的读写、加密,个人及各企事业单位可以根据自己的加密方式对卡片进行处理后使用。本例在VS2010及以上编译环境中测试通过。

运行界面:
在这里插入图片描述
想调试你得有这些:

德卡D3非接触式IC卡读写器(USB免驱)
在这里插入图片描述

IC芯片卡
在这里插入图片描述

D3 SDK
在这里插入图片描述

在操作之前先了解一下IC卡的一些基础知识(本例以M1卡为例):
M1卡有16个扇区,即0到15扇区,每个扇区4块,每块16个字节,以块为存取单位,要读取扇区中的数据,首先要进行密码校验(校验读卡设备中的密码和卡上的密码);要读取哪个扇区的数据就要校验哪个扇区的密码,dc_read或dc_read_hex方法是用的地址是绝对地址(每个扇区4个地址,16个扇区共64个地址,即0到63),校验完0扇区的密码后,能读取0到3地址上的数据,校验完1扇区的密码后,能读取4到7地址上的数据,以此类推。假设扇区号是 sNo,数据块号是dNo,则:sNo号扇区的最小区块号为:4 * sNo,最大区块号为:4 * sNo + 3。

存储结构
在这里插入图片描述

第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。
每个扇区的块0、块1、块2为数据块,可用于存贮数据。
每个扇区的块3为控制块,包括了密码A、存取控制、密码B。具体结构如下:
A0 A1 A2 A3 A4 A5 FF 07 80 69 B0 B1 B2 B3 B4 B5

对IC卡操作的基本步骤:

初始化InitIC() -> 寻卡ReadIc() -> 校验密码getKeys(string cardID) -> 加密操作LoadKeysToCard(string cardID) -> 关闭串口ExitIC()。

本例测试用卡片的特定加密方式:

  • 卡号+“ZMATRIX”+扇区号。
  • 经MD5加密后取前12位字符形成字符串。
  • 对字符串进行BCD码加密。
  • 组合秘钥形成完整控制块数据。
  • 写入卡片进行加密。

核心函数的代码:

/// <summary>
/// 寻卡
/// </summary>
/// <returns>物理卡号</returns>
public string ReadIc()
{
    uint st = 4;
    ulong icCardNo = 0;
    char str = (char)0;
    string cardID = "";
    int card = dc_card((Int16)_icdev, str, ref icCardNo);
    if(card == 0)
    {
        string strCardID = Ten2Hex(icCardNo);
        cardID = FormatCardID(String.Format("{0:X}", strCardID));
        cardUniID = cardID;
        MessageBox.Show("寻卡成功!");
    }
    else{
        MessageBox.Show("寻卡失败!");
    }
    return cardID;//16进制
}
/// <summary>       
/// 获取各扇区对应秘钥,核心函数       
/// </summary>       
/// <param name="cardID">卡物理号</param>       
private void getKeys(string cardID)       
{           
    int len = 16;
    byte[] bMoren = { 255, 255, 255, 255, 255, 255 };           
    byte[] bKey = new byte[6];           
    byte[] bData = new byte[16];
    string[] befEncrypt = new string[len];           
    string[] aftEncrypt = new string[len];
    for(int sector = 0 ; sector < len ; sector++)           
    {               
        befEncrypt[sector] = cardID + "ZMATRIX" + sector.ToString();               
        aftEncrypt[sector] = MD5.MD5Encrypt(befEncrypt[sector], 32).Substring(0, 12);
        bKey = BCDEncrypt.str2Bcd(aftEncrypt[sector]);               
        int checkNum = dc_authentication_passaddr(_icdev, 4, (sector * 4 + 3), bKey);
        if (checkNum == 0)               
        {                   
            MessageBox.Show("验证第" + (sector * 4 + 3) + "块密码成功!");                   
            int readData = dc_read(_icdev, sector * 4 + 3, bData);
        }else{                   
            MessageBox.Show("验证第" + (sector * 4 + 3) + "块密码失败!");               
        }           
    }       
}
/// <summary>      
/// 新卡加密,核心函数       
/// </summary>       
/// <param name="cardID">新卡序列号(物理卡号)</param>       
private void LoadKeysToCard(string cardID)     
{           
    byte[] bKey = new byte[6];           
    string[] befEncrypt = new string[16];           
    string[] aftEncrypt = new string[16];           
    byte[] bMoren = { 255, 255, 255, 255, 255, 255 };           
    lbl = getLabel();//Label集          
    lblTips.Text = "";
    for (int sector = 0; sector < 16; sector++)           
    {               
        int checkNum = dc_authentication_passaddr(_icdev, 4, (sector * 4 + 3),bMoren);              
        if (checkNum == 0)               
        {                   
            befEncrypt[sector] = cardID + "ZMATRIX" + sector.ToString();              
            aftEncrypt[sector] = MD5.MD5Encrypt(befEncrypt[sector], 32).Substring(0, 12);
            bKey = BCDEncrypt.str2Bcd(aftEncrypt[sector]);                  
            int writeOk = dc_write(_icdev, (sector * 4 + 3), CombineKey(bKey));                   
            if (writeOk == 0)                   
            {                       
                tip[sector] = 0;                   
            }else{                       
                tip[sector] = 1;                   
            }               
        }else{                   
            tip[sector] = 1;                  
            lblTips.Text = "失败:【该卡可能已加密】";                   
            lblTips.ForeColor = Color.Red;
        }          
    }
    Set_Text = new set_Text(set_LalColor);          
    thread1 = new Thread(new ThreadStart(run));           
    thread1.Start();      
}

源码下载:关注公众号『几行简码』,回复【读卡】即可获取下载链接。

原创文章,转载请务必先查阅公众号内【转载须知】。
加关注,不迷路

标签:sector,string,C#,IC卡,扇区,源码,cardID,new,255
来源: https://blog.csdn.net/njtsgseuzy/article/details/105241407

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有