实例介绍
【实例简介】
【实例截图】
【实例截图】
【核心代码】
#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 );
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论