基本信息
源码名称:CRT-571-V10 IC卡发卡机软件
源码大小:0.20M
文件格式:.rar
开发语言:C/C++
更新时间:2015-04-24
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
#include "stdafx.h" #include "dcic32.h" #include "CICcard.h" byte gstrPIN[] = {0x63 , 0x18 , 0x78 , 0x52 , 0x26 , 0x99 , 0x83 , 0x07 }; byte gstrver[]={ (byte)'B' , (byte)'K' , 0x00 , 0x01}; byte gdefPIN1[]= { 0x31, 0x32, 0x33, 0x34, 0xFF, 0xFF, 0xFF, 0xFF }; byte gdefPIN2[]= { 0x35, 0x36, 0x37, 0x38, 0xFF, 0xFF, 0xFF, 0xFF }; byte gstrPIN1[]= { 0x32, 0x36, 0x39, 0x39, 0x38, 0x33, 0x30, 0x37 }; byte gstrPIN2[]= { 0x32, 0x36, 0x39, 0x39, 0x38, 0x33, 0x30, 0x37 }; byte gdefPUK1[]= { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 }; byte gdefPUK2[]= { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 }; byte gnewPUK1[]= { 0x32, 0x36, 0x39, 0x39, 0x38, 0x33, 0x30, 0x37 }; byte gnewPUK2[]= { 0x32, 0x36, 0x39, 0x39, 0x38, 0x33, 0x30, 0x37 }; CICcard::CICcard() { icdev = 0; st = 0; ic_type=-1; ICerror = 0; ICstate = -1; iPrgAuth = -1; gCardType = -1; icdev=NULL; } CICcard::~CICcard() { Close(); } /// <summary> /// 校验个人密码 /// </summary> /// <param name="keyleft">控制密码左8位</param> /// <param name="keyleft">控制密码右8位</param> /// <returns></returns> short CICcard::IC_VerifyPIN(byte* CtlKey , byte* strPIN) { byte Randdata_hex[64]; byte keyright[8]; byte sedata[64]; byte relen = 0; byte outbuf[64]; short st; if (gCardType == 0) { //1.取随机数 st = IC_GetChallenge(Randdata_hex); if (st != 0) { //error ICerror = 201; return -1; } IC_Strcat(keyright, 0, CtlKey, 8, 8); //3.算密钥 /*8字节PIN密文计算方法:使用16字节3DES控制密钥(初始值为全FF) * 对8字节随机数加密得到8字节密文数据作为过程密钥;用这个过程密钥 * 对8字节PIN原文(初始值为8字节唯一芯片序列号,可以通过Reset PIN指令重置, * 11 11 11 11 11 11 11 11)进行DES加密得到8字节PIN密文。*/ byte temp1[64]; byte temp2[64]; st = IC_DES3(CtlKey, keyright, Randdata_hex, temp1); st = IC_Encrypt((char*)temp1, (char*)strPIN, 8, (char*)temp2); //sedata=sedata temp2; if (st != 0) { //error ICerror = 201; return -1; } //4.认证密钥 //00200008 sedata[0] = 0; sedata[1] = 0x20; sedata[2] = 0; sedata[3] = 0; sedata[4] = 8; sedata[5] = 0; IC_Strcat(sedata, 5, temp2, 0, 8); st = IC_CpuApdu(icdev, 13, sedata, &relen, outbuf); if ((st != 0)||(outbuf[0]!=0x90)) { //error ICerror = 202; return -1; } } else { if (CtlKey[0] == 1) { //验证PIN1 //A0 20 00 01 08 sedata[0] = 0xA0; sedata[1] = 0x20; sedata[2] = 0; sedata[3] = 1; sedata[4] = 8; sedata[5] = 0; IC_Strcat(sedata, 5, strPIN, 0, 8); st = IC_CpuApdu(icdev, 13, sedata, &relen, outbuf); if ((st != 0)||(outbuf[0]!=0x90)) { //error ICerror = 202; return -1; } } else if (CtlKey[0] == 2) { //验证PIN2 //A0 20 00 02 08 sedata[0] = 0xA0; sedata[1] = 0x20; sedata[2] = 0; sedata[3] = 2; sedata[4] = 8; sedata[5] = 0; IC_Strcat(sedata, 5, strPIN, 0, 8); st = IC_CpuApdu(icdev, 13, sedata, &relen, outbuf); if ((st != 0) || (outbuf[0] != 0x90)) { //error ICerror = 202; return -1; } } } return 0; } // / <summary> // / 选择IC卡文件 // / </summary> // / <param name="fileid">文件ID</param> // / <returns>0 成功</returns> short CICcard::IC_SelectFile(unsigned short offset) { byte relen = 0; byte tempbuf[128]; short st; if (gCardType == 1) { //组成命令 //A0A40000021F00 byte sedata[64]; sedata[0] = 0xa0; sedata[1] = 0xa4; sedata[2] = 0x00; sedata[3] = 0x00; sedata[4] = 0x02; sedata[5] = 0x1f; sedata[6] = 0x00; if (offset < (20 * 1024)) { sedata[6] = (byte)(offset / (4 * 1024)); } else { sedata[6] = (byte)(5 (offset - (20 * 1024)) / 3584);//(3.5 * 1024); } st = IC_CpuApdu(icdev, 7, sedata, &relen, tempbuf); // || (tempbuf[0] != 0x90)) if (st != 0) { //error ICerror = 301; return -1; } } return 0; } short CICcard::IC_EnablePIN(byte PINtype,byte* newPIN) { byte relen = 0; byte tempbuf[128]; short st; if (gCardType == 1) { //组成命令 //A028000108 byte sedata[64]; sedata[0] = 0xa0; sedata[1] = 0x28; sedata[2] = 0x00; sedata[3] = PINtype; sedata[4] = 0x08; IC_Strcat(sedata, 5, newPIN, 0, 8); st = IC_CpuApdu(icdev, 13, sedata, &relen, tempbuf); // || (tempbuf[0] != 0x90)) if (st != 0) { //error ICerror = 301; return -1; } } return 0; } /// <summary> /// 解锁IC卡密码 /// </summary> /// <param name="newPIN">解锁新PIN密钥</param> /// <returns>0 成功</returns> short CICcard::IC_UnblockPIN(byte PINtype, byte* newPUK, byte* newPIN) { byte relen = 0; byte tempbuf[128]; short st; if (gCardType == 1) { //组成命令 //A02C000x10 byte sedata[64]; sedata[0] = 0xa0; sedata[1] = 0x2c; sedata[2] = 0x00; sedata[3] = PINtype; sedata[4] = 0x10; IC_Strcat(sedata, 5, newPUK, 0, 8); IC_Strcat(sedata, 13, newPIN, 0, 8); st = IC_CpuApdu(icdev, 21, sedata, &relen, tempbuf); // if ((st != 0)|| (tempbuf[0] != 0x90)) { //error ICerror = 301; return -1; } } return 0; } /// <summary> /// 读IC卡数据 /// </summary> /// <param name="offset">偏移</param> /// <param name="len">读取长度</param> /// <param name="buf">输出数据缓存</param> /// <returns></returns> short CICcard::IC_ReadData( unsigned short offset , unsigned short len , byte* buf ) { int rlen=0; byte relen = 0; byte tempbuf[512]; short st; if (gCardType == 0) { //组成命令 byte sedata[64]; sedata[0] = 0; sedata[1] = 0xb0; while (rlen < len) { if ((len - rlen) > 112) { /*循环取数据*/ sedata[2] = (byte)((((offset rlen)) >> 8) & 0xFF); sedata[3] = (byte)((offset rlen) & 0xFF); sedata[4] = 112; sedata[5] = 0; st = IC_CpuApdu(icdev, 5, sedata, &relen, tempbuf); if ((st != 0) || (tempbuf[relen-2] != 0x90)) { //error ICerror = 301; return -1; } tempbuf[relen - 2] = 0; IC_Strcat(buf, rlen, tempbuf, 0, relen - 2); rlen = 112; } else { /*循环取数据*/ sedata[2] = (byte)((((offset rlen)) >> 8) & 0xFF); sedata[3] = (byte)((offset rlen) & 0xFF); sedata[4] = (byte)(len - rlen); sedata[5] = 0; st = IC_CpuApdu(icdev, 5, sedata, &relen, tempbuf); if ((st != 0) || (tempbuf[relen-2] != 0x90)) { //error ICerror = 301; return -1; } //去除返回码 tempbuf[relen - 2] = 0; IC_Strcat(buf, rlen, tempbuf, 0, relen - 2); break; } } } else { byte packetlen = 250; //当前偏移 unsigned short curoffset = offset; byte isneedselectfile = 1; //本次循环OFFSET unsigned short fileoffset = 0; byte curreadlen = 0; //组成命令 // A0B0000010 byte sedata[64]; sedata[0] = 0xa0; sedata[1] = 0xb0; while (rlen < len) { //判断是否重新选择文件 if (isneedselectfile == 1) { IC_SelectFile(curoffset); isneedselectfile = 0; } if ((len - rlen) > packetlen) { //取得相对文件内部的offset if (curoffset < (20 * 1024)) { fileoffset = (unsigned short)(curoffset % (4 * 1024)); curreadlen = packetlen; //是否超出文件边界 if ((fileoffset packetlen) >= (4 * 1024)) { curreadlen = (byte)((4 * 1024) - fileoffset); isneedselectfile = 1; } } else { fileoffset = (unsigned short)((curoffset - (20 * 1024)) % 3584);//(3.5 * 1024); curreadlen = packetlen; //是否超出文件边界 if ((fileoffset packetlen) >= (3584)) { curreadlen = (byte)((3584) - fileoffset); isneedselectfile = 1; } } /*循环取数据*/ sedata[2] = (byte)((((fileoffset )) >> 8) & 0xFF); sedata[3] = (byte)((fileoffset ) & 0xFF); sedata[4] = curreadlen; sedata[5] = 0; st = IC_CpuApdu(icdev, 5, sedata, &relen, tempbuf); //if ((st != 0) || (tempbuf[0] != 0x90)) if (st != 0) { //error ICerror = 301; return -1; } tempbuf[relen - 2] = 0; IC_Strcat(buf, rlen, tempbuf, 0, relen - 2); rlen = curreadlen; curoffset = curreadlen; } else { //取得相对文件内部的offset if (curoffset < (20 * 1024)) { fileoffset = (unsigned short)(curoffset % (4 * 1024)); curreadlen = (byte)(len - rlen); //是否超出文件边界 if ((fileoffset (len - rlen)) >= (4 * 1024)) { curreadlen = (byte)((4 * 1024) - fileoffset); isneedselectfile = 1; } } else { fileoffset = (unsigned short)((curoffset - (20 * 1024)) % 3584);//(3.5 * 1024); curreadlen = (byte)(len - rlen); //是否超出文件边界 if ((fileoffset (len - rlen)) >= (3584)) { curreadlen = (byte)((3584) - fileoffset); isneedselectfile = 1; } } /*循环取数据*/ sedata[2] = (byte)((((fileoffset )) >> 8) & 0xFF); sedata[3] = (byte)((fileoffset ) & 0xFF); sedata[4] = (byte)(curreadlen); sedata[5] = 0; st = IC_CpuApdu(icdev, 5, sedata, &relen, tempbuf); //if ((st != 0) || (tempbuf[0] != 0x90)) if (st != 0) { //error ICerror = 301; return -1; } //去除返回码 tempbuf[relen - 2] = 0; IC_Strcat(buf, rlen, tempbuf, 0, relen - 2); rlen = curreadlen; curoffset = curreadlen; if (rlen == len) { break; } } } } return 0; } /// <summary> /// 写IC卡数据 /// </summary> /// <param name="offset">偏移</param> /// <param name="len">写长度</param> /// <param name="buf">数据缓存</param> /// <returns></returns> short CICcard::IC_UpdateData( unsigned short offset , unsigned short len ,int bufflen, byte* buf ) { int curlen=0; byte relen = 0; byte tempbuf[128]; short st; //判断参数合法行 if ( len>( bufflen )) { return -1; } if (gCardType == 0) { //组成命令 byte sedata[1024]; sedata[0] = 0; sedata[1] = 0xd6; while (curlen < len) { if ((len - curlen) > 112) { /*循环写数据*/ sedata[2] = (byte)((((offset curlen)) >> 8) & 0xFF); sedata[3] = (byte)((offset curlen) & 0xFF); sedata[4] = 112; sedata[112 5] = 0; IC_Strcat(sedata, 5, buf, curlen, 112); st = IC_CpuApdu(icdev, (112 5), sedata, &relen, tempbuf); if ((st != 0) || (tempbuf[relen-2] != 0x90)) { //error ICerror = 301; return -1; } curlen = 112; } else { /*循环写数据*/ sedata[2] = (byte)((((offset curlen)) >> 8) & 0xFF); sedata[3] = (byte)((offset curlen) & 0xFF); sedata[4] = (byte)(len - curlen); sedata[(len - curlen) 5] = 0; IC_Strcat(sedata, 5, buf, curlen, len - curlen); st = IC_CpuApdu(icdev, (byte)((len - curlen) 5), sedata, &relen, tempbuf); if ((st != 0) || (tempbuf[relen-2] != 0x90)) { //error ICerror = 301; return -1; } curlen = 112; break; } } } else { //校验写 byte pintype[]= { 0x2}; st = IC_VerifyPIN(pintype, gstrPIN2); if (st != 0) { //error ICerror = 301; return -1; } byte packetlen = 250; //当前偏移 unsigned short curoffset = offset; byte isneedselectfile = 1; //本次循环OFFSET unsigned short fileoffset = 0; byte curreadlen = 0; //组成命令 // A0D6000004 1234ABCD byte sedata[1024]; sedata[0] = 0xa0; sedata[1] = 0xd6; while (curlen < len) { //判断是否重新选择文件 if (isneedselectfile == 1) { IC_SelectFile(curoffset); isneedselectfile = 0; } if ((len - curlen) > packetlen) { //取得相对文件内部的offset if (curoffset < (20 * 1024)) { fileoffset = (unsigned short)(curoffset % (4 * 1024)); curreadlen = packetlen; //是否超出文件边界 if ((fileoffset packetlen) >= (4 * 1024)) { curreadlen = (byte)((4 * 1024) - fileoffset); isneedselectfile = 1; } } else { fileoffset = (unsigned short)((curoffset - (20 * 1024)) % 3584);//(3.5 * 1024); curreadlen = packetlen; //是否超出文件边界 if ((fileoffset packetlen) >= (3584)) { curreadlen = (byte)((3584) - fileoffset); isneedselectfile = 1; } } /*循环处理数据*/ sedata[2] = (byte)((((fileoffset)) >> 8) & 0xFF); sedata[3] = (byte)((fileoffset) & 0xFF); sedata[4] = curreadlen; sedata[5] = 0; IC_Strcat(sedata, 5, buf, curlen, curreadlen); st = IC_CpuApdu(icdev, (byte)(curreadlen 5), sedata, &relen, tempbuf); //if ((st != 0) || (tempbuf[0] != 0x90)) if (st != 0) { //error ICerror = 301; return -1; } curlen = curreadlen; curoffset = curreadlen; } else { //取得相对文件内部的offset if (curoffset < (20 * 1024)) { fileoffset = (unsigned short)(curoffset % (4 * 1024)); curreadlen = (byte)(len - curlen); //是否超出文件边界 if ((fileoffset (len - curlen)) >= (4 * 1024)) { curreadlen = (byte)((4 * 1024) - fileoffset); isneedselectfile = 1; } } else { fileoffset = (unsigned short)((curoffset - (20 * 1024)) % 3584);//(3.5 * 1024); curreadlen = (byte)(len - curlen); //是否超出文件边界 if ((fileoffset (len - curlen)) >= (3584)) { curreadlen = (byte)((3584) - fileoffset); isneedselectfile = 1; } } /*循环处理数据*/ sedata[2] = (byte)((((fileoffset)) >> 8) & 0xFF); sedata[3] = (byte)((fileoffset) & 0xFF); sedata[4] = (byte)(curreadlen); sedata[5] = 0; IC_Strcat(sedata, 5, buf, curlen, curreadlen); st = IC_CpuApdu(icdev, (byte)(curreadlen 5), sedata, &relen, tempbuf); if ((st != 0) || (tempbuf[0] != 0x90)) { //error ICerror = 301; return -1; } curlen = curreadlen; curoffset = curreadlen; if (curlen == len) { break; } } } } return 0; } /// <summary> /// 3DES加密 /// </summary> /// <param name="keyleft">密钥低8位</param> /// <param name="keyright">密钥高8位</param> /// <param name="psrc">源串</param> /// <param name="pdest">加密后的串</param> /// <returns></returns> short CICcard::IC_DES3( byte* keyleft , byte* keyright , byte* psrc , byte* pdest ) { byte temp1[8]; byte temp2[8]; IC_Encrypt((char*) keyleft , (char*)psrc , 8 ,(char*) temp1 ); IC_Decrypt((char*) keyright , (char*)temp1 , 8 ,(char*) temp2 ); IC_Encrypt((char*) keyleft ,(char*) temp2 , 8 ,(char*) pdest ); return 0; } short CICcard::IC_Strcat( byte* pdest , int doff , byte* psrc , int soff , int len ) { //判断参数合法性 /* if ( ( doff len ) > sizeof((char*)pdest) ) { return -1; } if ( ( soff len )>strlen((char*)psrc) ) { return -1; } */ for ( int i=0 ; i<len ; i ) { pdest[doff i]=psrc[soff i]; } return 0; } short CICcard::IC_GetChipID( byte* ChipID ) { byte Serdata_hex[64]; byte sedata[64]; byte relen = 0; short st; //1.取序列号 sedata[0] = 0; sedata[1] = 0x24; sedata[2] = 0; sedata[3] = 0; sedata[4] = 8; //{"0024000008"}; st = IC_CpuApdu( icdev , 5 , sedata , &relen , Serdata_hex ); if ((st != 0) || (Serdata_hex[relen-2] != 0x90)) { //error ICerror = 201; return -1; } IC_Strcat( ChipID , 0 , Serdata_hex , 0 , 8 ); return 0; } short CICcard::IC_GetChallenge( byte* Randdata ) { byte tempout[64]; byte sedata[64]; byte relen = 0; short st; //1.取随机数 sedata[0] = 0; sedata[1] = 0x84; sedata[2] = 0; sedata[3] = 0; sedata[4] = 8; //{"0084000008"}; st = IC_CpuApdu( icdev , 5 , sedata , &relen , tempout ); if ((st != 0) || (tempout[relen-2] != 0x90)) { //error ICerror = 201; return -1; } IC_Strcat( Randdata , 0 , tempout , 0 , 8 ); return 0; } /// <summary> /// 修改卡片控制密钥 /// </summary> /// <param name="oldctrl">旧控制密钥</param> /// <param name="newctl">新控制密钥</param> /// <returns>0 成功 -1 失败</returns> short CICcard::IC_ChangeCtrlkey( byte* oldctrl , byte* newctl ) { byte Randdata[64]; byte sedata[64]; byte relen = 0; short st; //1.取随机数 st = IC_GetChallenge( Randdata ); if ( st != 0 ) { //error ICerror = 201; return -1; } //使用16字节旧3DES控制密钥对8字节随机数加密得到8字节密文数据作为认证数据 byte tempstr[8]; byte keyright[8]; IC_Strcat( keyright , 0 , oldctrl , 8 , 8 ); IC_DES3( oldctrl , keyright , Randdata , tempstr ); IC_Strcat( sedata , 5 , tempstr , 0 , 8 ); //用16字节旧3DES控制密钥对新的3DES控制密钥的左8字节进行DES加密得到左8字节新3DES控制密钥密文 IC_DES3( oldctrl , keyright , newctl , tempstr ); IC_Strcat( sedata , 13 , tempstr , 0 , 8 ); //用16字节旧3DES控制密钥对新的3DES控制密钥的右8字节进行DES加密得到右8字节新3DES控制密钥密文 IC_Strcat( keyright , 0 , newctl , 8 , 8 ); IC_DES3( oldctrl , keyright , keyright , tempstr ); IC_Strcat( sedata , 21 , tempstr , 0 , 8 ); sedata[0] = 0x00; sedata[1] = 0x23; sedata[2] = 0x00; sedata[3] = 0x00; sedata[4] = 0x18; //"0023000018" st = IC_CpuApdu( icdev , 29 , sedata , &relen , Randdata ); if ((st != 0) || (Randdata[relen-2] != 0x90)) { //error ICerror = 201; return -1; } return 0; } /// <summary> /// 修改个人密钥 /// </summary> /// <param name="Ctlkey">控制密钥</param> /// <param name="oldPIN">旧密钥</param> /// <param name="newPIN">新密钥</param> /// <returns>0 成功 -1 失败</returns> short CICcard::IC_ChangePIN( byte* Ctlkey , byte* oldPIN , byte* newPIN ) { byte Randdata[64]; byte sedata[64]; byte relen = 0; short st; if (gCardType == 0) { //1.取随机数 st = IC_GetChallenge(Randdata); if (st != 0) { //error ICerror = 201; return -1; } //使用16字节3DES控制密钥对8字节随机数加密得到8字节密文数据作为过程密钥; byte tempstr[8]; byte keyright[8]; IC_Strcat(keyright, 0, Ctlkey, 8, 8); IC_DES3(Ctlkey, keyright, Randdata, tempstr); IC_Strcat(sedata, 5, tempstr, 0, 8); //用这个过程密钥对8字节旧PIN原文进行DES加密得到8字节旧PIN密文; byte oldPinEn[8]; IC_Encrypt((char*)tempstr, (char*)oldPIN, 8, (char*)oldPinEn); //用这个过程密钥对8字节新PIN原文进行DES加密得到8字节新PIN密文。 byte newPinEn[8]; IC_Encrypt((char*)tempstr, (char*)newPIN, 8, (char*)newPinEn); //0021000010 sedata[0] = 0x00; sedata[1] = 0x21; sedata[2] = 0x00; sedata[3] = 0x00; sedata[4] = 0x10; IC_Strcat(sedata, 5, oldPinEn, 0, 8); IC_Strcat(sedata, 13, newPinEn, 0, 8); st = IC_CpuApdu(icdev, 21, sedata, &relen, Randdata); if ((st != 0) || (Randdata[0] != 0x90)) { //error ICerror = 201; //判断返回值 if (relen == 2) { if (Randdata[0] != 0x90) { if (Randdata[0] == 0x63) { byte a; a = Randdata[1]; } } } return -1; } } else if (gCardType == 1) { byte outbuf[64]; if (Ctlkey[0] == 1) { //PIN1 //A0 24 00 PIN NO. 10 sedata[0] = 0xA0; sedata[1] = 0x24; sedata[2] = 0; sedata[3] = 1; sedata[4] = 0x10; sedata[5] = 0; IC_Strcat(sedata, 5, oldPIN, 0, 8); IC_Strcat(sedata, 13, newPIN, 0, 8); st = IC_CpuApdu(icdev, 21, sedata, &relen, outbuf); if ((st != 0) || (outbuf[0] != 0x90)) { //error ICerror = 202; return -1; } } else if(Ctlkey[0]==2) { //PIN2 //A0 24 00 PIN NO. 10 sedata[0] = 0xA0; sedata[1] = 0x24; sedata[2] = 0; sedata[3] = 2; sedata[4] = 0x10; sedata[5] = 0; IC_Strcat(sedata, 5, oldPIN, 0, 8); IC_Strcat(sedata, 13, newPIN, 0, 8); st = IC_CpuApdu(icdev, 21, sedata, &relen, outbuf); if ((st != 0) || (outbuf[0] != 0x90)) { //error ICerror = 202; return -1; } } } return 0; } short CICcard::IC_ResetPIN( byte* Ctlkey , byte* newPIN ) { byte Randdata[64]; byte sedata[64]; byte relen = 0; short st; //1.取随机数 st = IC_GetChallenge( Randdata ); if ( st != 0 ) { //error ICerror = 201; return -1; } //使用16字节3DES控制密钥对8字节随机数加密得到8字节密文数据作为认证数据; byte tempstr[8]; byte keyright[8]; IC_Strcat( keyright , 0 , Ctlkey , 8 , 8 ); IC_DES3( Ctlkey , keyright , Randdata , tempstr ); IC_Strcat( sedata , 5 , tempstr , 0 , 8 ); //用16字节3DES控制密钥对8字节新PIN原文进行DES加密得到8字节新PIN密文。 byte newPinEn[8]; IC_DES3( Ctlkey , keyright , newPIN , newPinEn ); IC_Strcat( sedata , 13 , newPinEn , 0 , 8 ); //0022000010 sedata[0] = 0x00; sedata[1] = 0x22; sedata[2] = 0x00; sedata[3] = 0x00; sedata[4] = 0x10; st = IC_CpuApdu( icdev , 21 , sedata , &relen , Randdata ); if ((st != 0) || (Randdata[relen-2] != 0x90)) { //error ICerror = 201; return -1; } return 0; } int CICcard::IC_GetCardType(byte* sATR) { if(strlen((char*)sATR)==0) { return -1; } if((sATR[5]==0x56)||(sATR[6]==0x12)) { return 0; } else if((sATR[5]==0x00)||(sATR[6]==0x81)) { return 1; } return -1; } /// <summary> /// IC卡模块初始化 /// </summary> /// <param name="ikey">程序模块初始化校验字符串</param> /// <returns>-1 读卡器错误 -2 未插卡 -3 读卡器错误 -4 卡片损坏(无法复位) -5 卡未初始化</returns> short CICcard::Init(CString ikey) { short iret; byte rlen; byte rbuf[64]; short st; // 一、对程序进行认证 // 对程序合法性进行验证 if ( ikey == ( "^A1&4CM." ) ) { iPrgAuth = 1; } else { //error ICerror = 100; IC_Beep( icdev , 100 , 3 ); iPrgAuth=0; return -1; } // 二、对设备初始化 // 1.初始化端口 icdev = IC_InitComm( 100 ); if ( icdev <= 0 ) { //error ICerror = 100; IC_Beep( icdev , 100 , 3 ); return -1; } // 2.初始化IC卡类型(CPU卡) iret = IC_InitType( icdev , 0x0C ); if ( iret != 0 ) { //error ICerror = 101; IC_Beep( icdev , 100 , 3 ); return -1; } // 3.取卡状态 iret = IC_Status( icdev ); if ( iret == 1 ) { //正确,但没卡 ICstate = 1; //未插卡 return -2; } else if ( iret==0 ) { ICstate = 2; } else { ICerror = 103; IC_Beep( icdev , 100 , 3 ); //读卡错误 return -3; } //卡复位 iret = IC_CpuReset( icdev , & rlen , rbuf ); if ( iret != 0 ) { //error ICerror = 201; //读卡错误,(可能插反) return -4; } //判断卡类型 gCardType = IC_GetCardType(rbuf); if(gCardType<0) { //error ICerror = 201; return -1; } //根据不同的卡类型做不同的初始化 if (gCardType == 0) { //设置波特率 byte bpsstring[] ={ 0xff, 0x10, 0x96 }; iret = IC_CpuApdu(icdev, 3, bpsstring, & rlen, rbuf); if (iret != 0) { //error ICerror = 201; return -1; } //三、对卡进行个人密码认证 byte defCtlkey[] ={ 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 }; #if 0 //test liufr byte serdata[8]; //默认PIN为序列号 iret = IC_GetChipID(serdata); if (iret != 0) { return -1; } //默认CTLkey为全FF iret = IC_VerifyPIN(defCtlkey, serdata); if (iret != 0) { return -1; } //test end #endif iret = IC_VerifyPIN( defCtlkey , gstrPIN ); if (iret != 0) { //未初始化 return -5; } } else { //设置波特率 byte bpsstring[] ={ 0xff, 0x10, 0x95 }; iret = IC_CpuApdu(icdev, 3, bpsstring, & rlen, rbuf); if (iret != 0) { //error ICerror = 201; return -1; } //校验写 byte pintype[] ={ 0x1 }; st = IC_VerifyPIN(pintype, gstrPIN1); if (st != 0) { //error ICerror = 301; //未初始化 return -5; } pintype[0] = 2; st = IC_VerifyPIN(pintype, gstrPIN2); if (st != 0) { //error ICerror = 301; //未初始化 return -5; } } //判断卡片初始化标识 byte strver[64]; iret =IC_ReadData( 0 , 4 , strver ); if ( iret!=0 ) { return -1; } if ( ( strver[0]!=gstrver[0] )||( strver[1]!=gstrver[1] ) ) { //未初始化 return -5; } return 0; } short CICcard::GetICStatus() { short iret; HANDLE tempdev=IC_InitComm(100); iret=IC_Status(tempdev); IC_ExitComm(tempdev); return iret; } short CICcard::FormatIC(CString ikey) { short iret; byte rlen; byte rbuf [64]; short st; // 一、对程序进行认证 // 对程序合法性进行验证 if ( ikey==( "^A1&4CM." ) ) { iPrgAuth = 1; } else { //error ICerror = 100; IC_Beep( icdev , 100 , 3 ); iPrgAuth=0; return -1; } // 二、对设备初始化 // 1.初始化端口 icdev = IC_InitComm( 100 ); if ( icdev <= 0 ) { //error ICerror = 100; IC_Beep( icdev , 100 , 3 ); return -1; } // 2.初始化IC卡类型(CPU卡) iret = IC_InitType( icdev , 0x0C ); if ( iret != 0 ) { //error ICerror = 101; IC_Beep( icdev , 100 , 3 ); return -1; } // 3.取卡状态 iret = IC_Status( icdev ); if ( iret == 1 ) { //正确,但没卡 ICstate = 1; return -2; } else if ( iret==0 ) { ICstate = 2; } else { ICerror = 103; IC_Beep( icdev , 100 , 3 ); return -1; } st= IC_CpuReset( icdev , & rlen , rbuf ); if ( st != 0 ) { //error ICerror = 201; return -1; } //判断卡类型 gCardType = IC_GetCardType(rbuf); if (gCardType < 0) { //error ICerror = 201; return -3; } if (gCardType == 0) { //三、对卡进行个人密码认证 //byte[] keyleft[] { 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 }; //byte[] keyright=new byte[] { 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 }; byte defCtlkey []= { 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 }; byte serdata[8]; //默认PIN为序列号 iret = IC_GetChipID(serdata); if (iret != 0) { return -1; } //默认CTLkey为全FF iret = IC_VerifyPIN(defCtlkey, serdata); if (iret != 0) { iret = IC_ClearPIN(); if (iret != 0) { return -3; } st = IC_CpuReset(icdev, & rlen, rbuf); if (st != 0) { //error ICerror = 201; return -1; } //默认CTLkey为全FF iret = IC_VerifyPIN(defCtlkey, serdata); } //写入唯一标识 'B' 'K' 0X00 0X01 byte defver[]= { (byte)'B' , (byte)'K' , 0x00 , 0x01 , 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; iret = IC_UpdateData(0, 4 14, 18,defver); if (iret != 0) { return -1; } //修改PIN iret = IC_ChangePIN(defCtlkey, serdata, gstrPIN); if (iret != 0) { return -1; } //默认CTLkey为全FF iret = IC_VerifyPIN(defCtlkey, gstrPIN); if (iret != 0) { return -1; } } else if(gCardType==1) { byte pintype[] ={ 0x1 }; //先打开密码验证功能 st = IC_EnablePIN(pintype[0], gdefPIN1); if (st != 0) { //error ICerror = 301; return -1; } pintype[0] = 2; st = IC_EnablePIN(pintype[0], gdefPIN2); if (st != 0) { //error ICerror = 301; return -1; } st = IC_CpuReset(icdev, & rlen, rbuf); if (st != 0) { //error ICerror = 201; return -1; } //三、对卡进行个人密码认证 pintype[0] = 1; st = IC_VerifyPIN(pintype, gdefPIN1); if (st != 0) { if (st != 0) { st = IC_ClearPIN(); if (st != 0) { return -3; } } } pintype[0] = 2; st = IC_VerifyPIN(pintype, gdefPIN2); if (st != 0) { //error ICerror = 301; return -1; } //改密码 pintype[0] = 1; st = IC_ChangePIN(pintype, gdefPIN1,gstrPIN1); if (st != 0) { //error ICerror = 301; return -1; } pintype[0] = 2; st = IC_ChangePIN(pintype, gdefPIN2, gstrPIN2); if (st != 0) { //error ICerror = 301; return -1; } pintype[0] = 1; st = IC_VerifyPIN(pintype, gstrPIN2); if (st != 0) { //error ICerror = 301; return -1; } pintype[0] = 2; st = IC_VerifyPIN(pintype, gstrPIN2); if (st != 0) { //error ICerror = 301; return -1; } //写入唯一标识 'B' 'K' 0X00 0X01 byte defver []= { (byte)'B' , (byte)'K' , 0x00 , 0x01 , 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; iret = IC_UpdateData(0, 4 14,18, defver); if (iret != 0) { return -1; } } return 0; } /// <summary> /// 重置IC卡密钥 /// </summary> /// <returns></returns> short CICcard::IC_ClearPIN() { //重置密钥 if (gCardType == 0) { byte defCtlkey[]= { 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 }; byte serdata [8]; //默认PIN为序列号 short iret = IC_GetChipID(serdata); if (iret != 0) { return -1; } iret = IC_ResetPIN(defCtlkey, serdata); if (iret != 0) { return -1; } } else if (gCardType == 1) { byte defpuk[]= { 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30}; byte gdefPIN1[] ={ 0x31, 0x32, 0x33, 0x34, 0xFF, 0xFF, 0xFF, 0xFF }; byte gdefPIN2[] ={ 0x35, 0x36, 0x37, 0x38, 0xFF, 0xFF, 0xFF, 0xFF }; //默认PIN为序列号 short iret = IC_UnblockPIN(0, defpuk, gdefPIN1); if (iret != 0) { return -1; } iret = IC_UnblockPIN(2,defpuk, gdefPIN2); if (iret != 0) { return -1; } } return 0; } short CICcard::Close() { short st; st = IC_Down( icdev ); if ( st != 0 ) { //error ICerror = 401; return -1; } st = IC_ExitComm( icdev ); if ( st != 0 ) { //error ICerror = 402; return -1; } return 0; } /// <summary> /// 响蜂鸣器 /// </summary> /// <param name="time">蜂鸣器响时长 毫秒</param> /// <returns>0 成功 -1 失败</returns> short CICcard::Beep(int time) { return IC_Beep( icdev , time , 1 ); } /// <summary> /// 写用户数据 /// </summary> /// <param name="type">数据类型</param> /// <param name="length">数据长度</param> /// <param name="byteArray">输入缓存</param> /// <returns></returns> short CICcard::WriteData(int type , unsigned short length , byte* byteArray) { short ret=0; unsigned short reallen=0; byte lenarray[]= { 0x00,0x00}; //长度判断 if ( length==0 ) { return 0; } //要写的长度比实际输入缓存要大,返回错误 if ( length>strlen((char*)byteArray )) { return -1; } if ( ( type>MAX_TYPE )||( type<1 ) ) { return -1; } //先将对应域长度清空 ret = IC_UpdateData( (unsigned short)(2 2*type) , 2 , 2,lenarray ); if ( ret!=0 ) { return -1; } switch ( type ) { //PARA112_TYPE case 1: if (length > PARA112_LEN) { reallen = PARA112_LEN; } else { reallen=length; } ret = IC_UpdateData(PARA112_OFFSET, reallen,length, byteArray); break; case 2: if (length > PARA512_LEN) { reallen = PARA512_LEN; } else { reallen = length; } ret = IC_UpdateData(PARA512_OFFSET, reallen,length, byteArray); break; //PERSON_TYPE =3 case 3: if ( length>PERSON_LEN ) { reallen = PERSON_LEN; } else { reallen=length; } ret = IC_UpdateData( PERSON_OFFSET , reallen ,length, byteArray ); break; //FINGER_TYPE = 4 case 4: if ( length>( FINGER_LEN ) ) { reallen = FINGER_LEN; } else { reallen=length; } ret = IC_UpdateData( FINGER_OFFSET , reallen ,length, byteArray ); break; //PHOTO_TYPE = 5 case 5: if ( length>( PHOTO_LEN ) ) { reallen = PHOTO_LEN; } else { reallen=length; } ret = IC_UpdateData( PHOTO_OFFSET , reallen ,length, byteArray ); break; default: return -1; } if ( ret!=0 ) { return -1; } //更新对应域实际长度 lenarray[0]=(byte)( ( reallen )&0xFF ); lenarray[1]=(byte)( ( ( ( reallen ) )>>8 )&0xFF ); ret = IC_UpdateData( (unsigned short)(2 2*type) , 2 ,2, lenarray ); if ( ret!=0 ) { return -1; } return ret; } /// <summary> /// 更新用户数据 /// </summary> /// <param name="type">数据类型 </param> /// <param name="databuf">用户数据信息</param> /// <returns></returns> short CICcard::WriteDatastr(int type , CString databuf) { short ret=0; //长度判断 if ( databuf.GetLength()==0 ) { return 0; } ret=this->WriteData( type , (unsigned short)(databuf.GetLength()) , (byte*)databuf.GetBuffer(databuf.GetLength()) ); return ret; } /// <summary> /// 写个人基本信息 /// </summary> /// <param name="datastr">个人信息</param> /// <returns></returns> short CICcard::WritePerson(CString datastr) { short ret=0; ret = WriteDatastr(PERSON_TYPE,datastr); return ret; } /// <summary> /// 写指纹信息 /// </summary> /// <param name="index">指纹编号 1~4</param> /// <param name="datastr">指纹信息</param> /// <returns>若编号输入有误,则返回-1</returns> short CICcard::WriteFinger(CString datastr) { short ret=0; ret = WriteDatastr((FINGER_TYPE),datastr); return ret; } short CICcard::WritePhoto(int len, byte* databuf) { short ret=0; ret=this->WriteData( PHOTO_TYPE , len , databuf ); return ret; } /// <summary> /// 读备用参数值 /// </summary> /// <param name="type">备用参数数据byte[]</param> /// <returns>0 成功 -1 失败</returns> short CICcard::WritePara112(int len, byte* databuf) { short ret=0; if(len>112) return -1; ret=this->WriteData( PARA112_TYPE , len , databuf ); return ret; } /// <summary> /// 读备用参数值 /// </summary> /// <param name="type">备用参数数据byte[]</param> /// <returns>0 成功 -1 失败</returns> short CICcard::WritePara512(int len, byte* databuf) { short ret=0; if(len>512) return -1; ret=this->WriteData( PARA512_TYPE , len , databuf ); return ret; } /// <summary> /// 读用户信息 /// </summary> /// <param name="type">数据类型 1~7(其他值返回-1)</param> /// <param name="type">数据长度 </param> /// <param name="databuf">用户数据信息</param> /// <returns>0 成功 -1 失败 输入数据长度为0,返回成功 输入数据长度大于databuf可容纳长度,返回-1</returns> short CICcard::ReadData(int type , unsigned short length , byte* databuf ) { short ret=0; unsigned short reallen=0; byte lenarray[]={ 0x00 , 0x00 }; ///清空 memset(databuf,0,length); if ( length==0 ) { return 0; } if ( ( type>MAX_TYPE )||( type<1 ) ) { return -1; } //先将对应域实际长度读出 ret = IC_ReadData( (unsigned short)(2 2*type), 2 , lenarray ); if ( ret!=0 ) { return -1; } //实际长度 reallen=(unsigned short)(lenarray[0] lenarray[1]*256); if(reallen==0) { return 0; } //由于在写入时,已经判断了长度必须在有效范围内,所以读取的时候不需再判断 //读小余实际长度的情况 if ( length<reallen ) { reallen=length; } switch ( type ) { //备用参数信息 case 1: ret = IC_ReadData(PARA112_OFFSET, reallen, databuf); break; //备用参数信息 case 2: ret = IC_ReadData(PARA512_OFFSET, reallen, databuf); break; //基本信息 case 3: ret = IC_ReadData((PERSON_OFFSET), reallen, databuf); break; //指纹信息 case 4: ret = IC_ReadData((FINGER_OFFSET), reallen, databuf); break; //图片 case 5: ret = IC_ReadData((PHOTO_OFFSET), reallen, databuf); break; default: return -1; } return ret; } short CICcard::ReadPerson(unsigned short bufferlen, byte* databuf ) { return ReadData( PERSON_TYPE ,bufferlen, databuf ); } short CICcard::ReadFinger(unsigned short bufferlen, byte* databuf ) { return ReadData( FINGER_TYPE ,bufferlen, databuf ); } short CICcard::ReadPhoto(unsigned short bufferlen, byte* databuf ) { return ReadData( PHOTO_TYPE ,bufferlen, databuf ); } short CICcard::ReadPara112(unsigned short bufferlen, byte* databuf ) { return ReadData( PARA112_TYPE ,bufferlen, databuf ); } short CICcard::ReadPara512(unsigned short bufferlen, byte* databuf ) { return ReadData( PARA512_TYPE ,bufferlen, databuf ); }