Qt_C++读写IC卡数据、修改IC卡认证密钥源码支持windows国产linux操作系统

文章描述了一个基于Android/Linux平台的RFID读写器NFC发卡器的编程接口,详细列出了IC卡的存储结构、特点以及一系列的读写、认证和控制函数,如piccreadex、piccwriteex等,用于读写卡片数据和管理卡片密码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  Android Linux RFID读写器NFC发卡器WEB可编程NDEF文本/智能海报/-淘宝网 (taobao.com)

 IC卡的特性

1、分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位;
2、每个扇区有独立的一组密码及访问控制;
3、每张卡有唯一序列号,为32位;
4、具有防冲突机制,支持多卡操作;
5、无电源,自带天线,内含加密控制逻辑和通讯逻辑电路;
6、数据保存期为10年,可改写10万次,读无限次;
7、工作温度:-20℃~50℃(湿度为90%);
8、工作频率:13.56MHZ;
9、通信速率:106 KBPS;
10、读写距离:10 cm以内。 

 IC卡的存储结构

1、M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,存贮结构如下图所示: 

2、第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。

3、每个扇区的块0、块1、块2为数据块,可用于存贮数据。

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

5、每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位。 

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QDebug>
#include "QLibrary"
#include "QMessageBox"


#define BLOCK0_EN   0x01   //读写块0
#define BLOCK1_EN   0x02   //读写块1
#define BLOCK2_EN   0x04   //读写块2
#define NEEDSERIAL  0x08   //写指定序列号的卡
#define EXTERNKEY   0x10   //需要每次指定密码
#define NEEDHALT    0x20   //写卡后是否休眠卡

unsigned char oldblock[16];  //记录读取的块数据

//让读写器发出声音
typedef  unsigned char (*pcdbeep)(unsigned long xms);
#ifdef Q_OS_WIN
pcdbeep mypcdbeep = (pcdbeep)QLibrary("OUR_MIFARE.dll").resolve("pcdbeep");
#else
pcdbeep mypcdbeep = (pcdbeep)QLibrary("./libOURIDR.so").resolve("pcdbeep");
#endif

//返回本读写器独一无二的设备编号
typedef  unsigned char (*pcdgetdevicenumber)(unsigned char *devicenumber);
#ifdef Q_OS_WIN
pcdgetdevicenumber mypcdgetdevicenumber = (pcdgetdevicenumber)QLibrary("OUR_MIFARE.dll").resolve("pcdgetdevicenumber");
#else
pcdgetdevicenumber mypcdgetdevicenumber = (pcdgetdevicenumber)QLibrary("./libOURMIFARE.so").resolve("pcdgetdevicenumber");
#endif

//寻卡获取卡号
typedef unsigned char (*piccrequest)(unsigned char *serial);
#ifdef Q_OS_WIN
piccrequest mypiccrequest = (piccrequest)QLibrary("OUR_MIFARE.dll").resolve("piccrequest");
#else
piccrequest mypiccrequest = (piccrequest)QLibrary("./libOURIDR.so").resolve("piccrequest");
#endif

//轻松读卡
typedef unsigned char (*piccreadex)(unsigned char ctrlword,unsigned char *serial,unsigned char area,unsigned char keyA1B0,unsigned char *picckey,unsigned char *piccdata0_2);
#ifdef Q_OS_WIN
piccreadex mypiccreadex = (piccreadex)QLibrary("OUR_MIFARE.dll").resolve("piccreadex");
#else
piccreadex mypiccreadex = (piccreadex)QLibrary("./libOURIDR.so").resolve("piccreadex");
#endif

//轻松写卡
typedef unsigned char (*piccwriteex)(unsigned char ctrlword,unsigned char *serial,unsigned char area, unsigned char keyA1B0,unsigned char *picckey,unsigned char *piccdata0_2);
#ifdef Q_OS_WIN
piccwriteex mypiccwriteex = (piccwriteex)QLibrary("OUR_MIFARE.dll").resolve("piccwriteex");
#else
piccwriteex mypiccwriteex = (piccwriteex)QLibrary("./libOURIDR.so").resolve("piccwriteex");
#endif

//校验卡片扇区密码piccauthkey1
typedef unsigned char (*piccauthkey1)(unsigned char *serial,unsigned char area, unsigned char keyA1B0,unsigned char *picckey);
#ifdef Q_OS_WIN
piccauthkey1 mypiccauthkey1 = (piccauthkey1)QLibrary("OUR_MIFARE.dll").resolve("piccauthkey1");
#else
piccauthkey1 mypiccauthkey1 = (piccauthkey1)QLibrary("./libOURIDR.so").resolve("piccauthkey1");
#endif

//改单区密码
typedef unsigned char (*piccchangesinglekeyex)(unsigned char ctrlword,unsigned char *serial,unsigned char area,unsigned char keyA1B0,unsigned char *piccoldkey,unsigned char *piccdata);
#ifdef Q_OS_WIN
piccchangesinglekeyex mypiccchangesinglekeyex = (piccchangesinglekeyex)QLibrary("OUR_MIFARE.dll").resolve("piccchangesinglekeyex");
#else
piccchangesinglekeyex mypiccchangesinglekeyex = (piccchangesinglekeyex)QLibrary("./libOURIDR.so").resolve("piccchangesinglekeyex");
#endif

//读出一块的数据,也就是16个字节
typedef unsigned char (*piccread)(unsigned char block,unsigned char *piccdata);
#ifdef Q_OS_WIN
piccread mypiccread = (piccread)QLibrary("OUR_MIFARE.dll").resolve("piccread");
#else
piccread mypiccread = (piccread)QLibrary("./libOURIDR.so").resolve("piccread");
#endif

//写一块数据16字节 piccwrite
typedef unsigned char (*piccwrite)(unsigned char block,unsigned char *piccdata);
#ifdef Q_OS_WIN
piccwrite mypiccwrite = (piccwrite)QLibrary("OUR_MIFARE.dll").resolve("piccwrite");
#else
piccwrite mypiccwrite = (piccwrite)QLibrary("./libOURIDR.so").resolve("piccwrite");
#endif

//写0区0块 piccwriteserial
typedef unsigned char (*piccwriteserial)(unsigned char ctrlword,unsigned char *serial,unsigned char keyA1B0,unsigned char *picckey,unsigned char *piccdata0_2);
#ifdef Q_OS_WIN
piccwriteserial mypiccwriteserial = (piccwriteserial)QLibrary("OUR_MIFARE.dll").resolve("piccwriteserial");
#else
piccwriteserial mypiccwriteserial = (piccwriteserial)QLibrary("./libOURIDR.so").resolve("piccwriteserial");
#endif


//检测输入数据是否为16进制数
static bool checkinput(QString inputstr){
    QString inputyes="0123456789abcdefABCDEF";
    for(int i=0;i<inputstr.length();i++){
        if(inputyes.contains(inputstr.mid(i,1),Qt::CaseSensitive)){
        }else{return false;}
    }
    return true;
}

//检测动态库文件是否在运行目录内
static bool checkdllos(){
#ifdef Q_OS_WIN
    QLibrary mylib("OUR_MIFARE.dll");
    if (!mylib.load()){                //判断windows系统下,OUR_MIFARE.dll是否在运行目录内
        QMessageBox::information(NULL, "提示", "请将OUR_MIFARE.dll文件拷贝到生成exe文件相同目录下!");
        return false;
    }else{return true;}
#else
    QLibrary mylib("./libOURIDR.so");
    if (!mylib.load()){                //判断linux系统下,libOURIDR.so是否正运行目录内
        QMessageBox::information(NULL, "提示", "请将libOURIDR.so文件拷贝到生成的运行文件相同目录下!");
        return false;
    }else{return true;}
#endif
}


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->comboBox_2->setCurrentIndex(1);
}

MainWindow::~MainWindow()
{
    delete ui;
}


static QString DecimalToHex(long long decimal)
{
    QString hex = "";
    while (decimal > 0)
    {
        int remainder = decimal % 16;
        if (remainder < 10)
            hex = (char)(remainder + '0') + hex;
        else
            hex = (char)(remainder + 'A' - 10) + hex;
        decimal /= 16;
    }
    return hex;
}

//显示返回的错误代码信息
static void disperrinf(unsigned char result){
    switch (result) {
    case 1:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",0~2块都没读出来,可能刷卡太块。但卡序列号已被读出来!");
        break;
    case 2:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",第0块已被读出,但1~2块读取失败。卡序列号已被读出来!");
        break;
    case 3:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",第0、1块已被读出,但2块读取失败。卡序列号已被读出来!");
        break;
    case 8:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",未寻到卡,请重新拿开卡后再放到感应区!");
        break;
    case 9:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",有多张卡在感应区,寻卡过程中防冲突失败,读序列吗错误!");
        break;
    case 10:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",该卡可能已被休眠,无法选中卡片!");
        break;
    case 11:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",密码装载失败!");
        break;
    case 12:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",卡片密码认证失败!");
        break;
    case 13:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",读指定块失败,原因是刷卡太快或本块所对应的区还没通过密码认证!");
        break;
    case 14:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",写指定块失败,原因是刷卡太快或本块所对应的区还没通过密码认证!");
        break;
    case 18:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",写UID失败,此卡可能不是UID卡!");
        break;
    case 22:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",动态库或驱动程序异常!");
        break;
    case 23:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",驱动程序错误或发卡器尚未安装!");
        break;
    case 24:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",操作超时,一般是动态库没有反应!");
        break;
    case 25:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",发送字数不够!");
        break;
    case 26:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",驱动程序错误或发卡器尚未安装!");
        break;
    case 27:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",操作超时,一般是动态库没有反应!");
        break;
    case 28:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",发送字数不够!");
        break;
    default:
        QMessageBox::critical(NULL, "提示", QString::asprintf("错误代码:%d", result)+",未知的错误信息!");
        break;
    }
}



void MainWindow::on_pushButton_beep_clicked()
{
    if(!checkdllos()){return;}

    unsigned char status;
    status = mypcdbeep(30);
    if(status==0){
        ui->listWidget->addItem("发卡器已响应响声指令!");
    }
    else
    {
        disperrinf(status);
    }
}


void MainWindow::on_pushButton_getdevicenum_clicked()
{
    if(!checkdllos()){return;}        //判断运行目录内动态库文件是否存在

    unsigned char devicenumber[4];    //设备编号缓冲
    unsigned char status;             //函数返回状态
    if (mypcdgetdevicenumber != NULL){         //是否成功连接上 pcdgetdevicenumber()函数
        status = mypcdgetdevicenumber(devicenumber);
        if(status==0){
            mypcdbeep(30);
            ui->listWidget->addItem( QString::asprintf("设备编号:%03d-%03d-%03d-%03d", devicenumber[0],devicenumber[1],devicenumber[2],devicenumber[3]));
        }
        else
        {
            disperrinf(status);
        }
    }else{
        QMessageBox::critical(NULL, "提示", "函数‘pcdgetdevicenumber’未正确载入,请查询DLL文件版本是否正确!");
    }
}


void MainWindow::on_pushButton_clearlist_clicked()
{
    ui->listWidget->clear();
}


void MainWindow::on_pushButton_piccreadex_clicked()
{
    if(!checkdllos()){return;}

    unsigned char ctrlword;         //控制字
    unsigned char serial[4];        //可写数组,存放4字节卡UID
    unsigned char area;             //读出的区号
    unsigned char keyA1B0;          //AB密码认证
    unsigned char picckey[6];       //存放卡密码的数组
    unsigned char piccdata0_2[48];  //下标0~15存放作为读出的块0的数据,下标16~31存放作为读出的块1的数据,下标32~47存放作为读出的块2的数据
    unsigned char status;           //返回
    unsigned char piccdata[16];     //卡数据缓冲

    //以下控制字含义:读块0、块1、块2,仅读指定序列号的卡,需要每次指定密码
    if (ui->radioButton->isChecked()){
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;  //外部密码
    }else{
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;  //内部密码
    }
    area = ui->comboBox->currentIndex();           //操作扇区号
    keyA1B0 = ui->comboBox_2->currentIndex();      //密码认证类型,;大于0用A密码 ,等于0用B密码

    QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();

    if(Key_str.length()==12 and checkinput(Key_str)){
        for(int i=0;i<6;i++){
            bool ok;
            picckey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
        }
        status = mypiccreadex(ctrlword,serial,area,keyA1B0,picckey,piccdata0_2);    //读取选定扇区的0、1、2块
        if(status == 0){
            unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3];  //8H10D正码
            QString cardstr=QString::asprintf("%010d",card10);
            QString CardnoHex="";
            for(int i=0;i<4;i++){
                CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
            }
            QString blockdata="";
            for(int i=0;i<16;i++){
                blockdata=blockdata+QString::asprintf("%02X ", piccdata0_2[i]);
            }
            ui->textEdit_block0->setText(blockdata);
            blockdata="";
            for(int i=16;i<32;i++){
                blockdata=blockdata+QString::asprintf("%02X ", piccdata0_2[i]);
            }
            ui->textEdit_block1->setText(blockdata);
            blockdata="";
            for(int i=32;i<48;i++){
                blockdata=blockdata+QString::asprintf("%02X ", piccdata0_2[i]);
            }
            ui->textEdit_block2->setText(blockdata);

            status = mypiccread(area * 4 + 3,piccdata);   //读取选定扇区的第3块 A密码、控制位、B密码,无法读取的信息返回 00
            if(status == 0){
                blockdata="";
                for(int i=0;i<16;i++){
                    blockdata=blockdata+QString::asprintf("%02X ", piccdata[i]);
                }
                ui->textEdit_newkey->setText(blockdata);
                mypcdbeep(30);
                ui->listWidget->addItem("读取扇区数据成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
            }else{
                ui->textEdit_newkey->clear();
                disperrinf(status);
            }

        }else{
            ui->textEdit_block0->clear();
            ui->textEdit_block1->clear();
            ui->textEdit_block2->clear();
            ui->textEdit_newkey->clear();
            disperrinf(status);
        }
    }else{
        QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
    }
}


void MainWindow::on_pushButton_piccwriteex_clicked()
{
    if(!checkdllos()){return;}

    unsigned char ctrlword;        //控制字
    unsigned char serial[4];       //可写数组
    unsigned char area;            //操作扇区区号
    unsigned char keyA1B0;         //AB密码认证
    unsigned char picckey[6];      //存放卡密码的数组
    unsigned char piccdata0_2[48]; //下标0~15存放作为读出的块0的数据,下标16~31存放作为读出的块1的数据,下标32~47存放作为读出的块2的数据
    unsigned char status;          //返回
    char s;

    //以下控制字含义:读块0、块1、块2,仅读指定序列号的卡,需要每次指定密码
    if (ui->radioButton->isChecked()){
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;  //外部密码
    }else{
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;  //内部密码
    }
    area = ui->comboBox->currentIndex();           //操作扇区号
    keyA1B0 = ui->comboBox_2->currentIndex();      //密码认证类型,;大于0用A密码 ,等于0用B密码

    QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
    if(Key_str.length()==12 and checkinput(Key_str)){
        for(int i=0;i<6;i++){
            bool ok;
            picckey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
        }
    }else{
        QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
        return;
    }

    //检测写卡数据
    QChar ch;
    QString writinf = ui->textEdit_block0->toPlainText().trimmed()+ui->textEdit_block1->toPlainText().trimmed()+ui->textEdit_block2->toPlainText().trimmed();
    QString writinf1 = "";
    int m = 0;
    int n = 0;

    ch = writinf.at(0);
    s = writinf.at(0).toLatin1();
    for(int i=0; i<writinf.length() ; i++)
    {
        ch = writinf.at(i);
        s = writinf.at(i).toLatin1();
        if((('0' <= s) && (s <= '9')) || (('A' <= s) && (s <= 'F')) || (('a' <= s) && (s <= 'f')))
        {
            writinf1 += ch;
            n++;
            if(n==2){
                bool ok;
                piccdata0_2[m++] = writinf1.toInt(&ok,16);
                writinf1 = "";
                n = 0;
                if(m>=48){
                    break;
                }
            }
        }
        else if(s == ' '){

        }
        else
        {
            if(m>=0 && m<16){
                QMessageBox::critical(NULL, "提示", "第0块写卡数据错误,请输入正确的16进制数据!");
                //ui->textEdit_block0->setExtraSelections((m%16*3,2);
                ui->textEdit_block0->setFocus();
            }else if(m>=16 && m<32){
                QMessageBox::critical(NULL, "提示", "第1块写卡数据错误,请输入正确的16进制数据!");
                //ui->textEdit_block1.->setSelection(m%16*3,2);
                ui->textEdit_block1->setFocus();
            }else if(m>=32 && m<48){
                QMessageBox::critical(NULL, "提示", "第2块写卡数据错误,请输入正确的16进制数据!");
                //ui->textEdit_block2->setSelection(m%16*3,2);
                ui->textEdit_block2->setFocus();
            }
            return;
        }
    }

    status = mypiccwriteex(ctrlword,serial,area,keyA1B0,picckey,piccdata0_2);
    if(status == 0)
    {
        mypcdbeep(30);
        unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3];  //8H10D正码
        QString cardstr=QString::asprintf("%010d",card10);
        QString CardnoHex="";
        for(int i=0;i<4;i++){
            CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
        }
        ui->listWidget->addItem("写数据到扇区成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
    }else{
        disperrinf(status);
    }
}


void MainWindow::on_pushButton_piccchangesinglekey_clicked()
{
    if(!checkdllos()){return;}

    unsigned char ctrlword;     //控制字
    unsigned char serial[4];    //可写数组
    unsigned char area;         //操作扇区号
    unsigned char keyA1B0;      //AB密码认证方式
    unsigned char piccoldkey[6];//存放卡原始密码的数组
    unsigned char piccdata[17]; //存放卡新A密码(也就是准备改成的密码)、密码权限访问字、新B密码的数组、指定更改项目的标志
    unsigned char status;       //返回

    //以下控制字含义:读块0、块1、块2,仅读指定序列号的卡,需要每次指定密码
    if (ui->radioButton->isChecked()){
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;  //外部密码
    }else{
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;  //内部密码
    }
    area = ui->comboBox->currentIndex();               //操作扇区号
    keyA1B0 = ui->comboBox_2->currentIndex();          //密码认证类型,;大于0用A密码 ,等于0用B密码

    QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
    if(Key_str.length()==12 and checkinput(Key_str)){
        for(int i=0;i<6;i++){
            bool ok;
            piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
        }
    }else{
        QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
        return;
    }

    QChar ch;
    QString writinf = ui->textEdit_newkey->toPlainText().trimmed();
    QString writinf4 = "";
    int m = 0;
    int n = 0;
    char s;
    for(int i=0; i<writinf.length() ; i++)
    {
        ch = writinf.at(i);
        s = writinf.at(i).toLatin1();
        if((('0' <= s) && (s <= '9')) || (('A' <= s) && (s <= 'F')) || (('a' <= s) && (s <= 'f')))
        {
            writinf4 += ch;
            n++;
            if(n==2){
                bool ok;
                piccdata[m++] = writinf4.toInt(&ok,16);
                writinf4 = "";
                n = 0;
                if(m>=16){
                    break;
                }
            }
        }
        else if(s == ' ') {

        }
        else
        {
            QMessageBox::critical(NULL, "提示", "新A、B密码及控制位输入错误,请输入正确的16进制数据!");
            //ui->textEdit_newkey->setSelection(i,1);
            ui->textEdit_newkey->setFocus();
            return;
        }
    }

    if(m<16)
    {
        QMessageBox::critical(NULL, "提示", "新A、B密码及控制位输入错误,请输入正确的16进制数据!");
        ui->textEdit_newkey->setFocus();
        return;
    }

    piccdata[16]=ui->comboBox_3->currentIndex();   //取值0表示只改A密码,2表示改A、B密码,3表示修改A、B及控制位
    if(piccdata[16]>0){piccdata[16]=piccdata[16]+1;}

    int answ=QMessageBox::question (this, "警告", "你确定修改密码控制块的数据吗 ?此数据块如果改写错误,数据卡将会被限制!", QMessageBox::Ok, QMessageBox::Cancel);
    if (answ ==1024){
        status = mypiccchangesinglekeyex(ctrlword,serial,area,keyA1B0,piccoldkey,piccdata);
        if(status == 0){
            mypcdbeep(30);
            unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3];  //8H10D正码
            QString cardstr=QString::asprintf("%010d",card10);
            QString CardnoHex="";
            for(int i=0;i<4;i++){
                CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
            }
            ui->listWidget->addItem("修改扇区密码成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
        }else {
            disperrinf(status);
        }
    }
}


void MainWindow::on_pushButton_piccread_clicked()
{
    if(!checkdllos()){return;}

    unsigned char serial[4];    //可写数组
    unsigned char area;         //操作扇区号
    unsigned char keyA1B0;      //AB密码认证方式
    unsigned char piccoldkey[6];//存放卡原始密码的数组
    unsigned char piccdata[16]; //存放块数据
    unsigned char status;       //返回

    int myblock=ui->spinBox->value();
    area=myblock/4;

    QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
    if(Key_str.length()==12 and checkinput(Key_str)){
        for(int i=0;i<6;i++){
            bool ok;
            piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
        }
    }else{
        QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
        return;
    }

    status = mypiccrequest(serial);  //寻卡获取到卡号
    if(status == 0){
        unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3];  //8H10D正码
        QString cardstr=QString::asprintf("%010d",card10);
        QString CardnoHex="";
        for(int i=0;i<4;i++){
            CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
        }
        status = mypiccauthkey1(serial,area,keyA1B0,piccoldkey);
        if(status == 0){
            status = mypiccread(myblock,piccdata);
            if(status == 0){
                mypcdbeep(30);
                QString blockdata="";
                for(int i=0;i<16;i++){
                    blockdata=blockdata+QString::asprintf("%02X ", piccdata[i]);
                    oldblock[i]=piccdata[i];    //保存读取的块数据,用于复制uid
                }
                ui->textEdit_thisblock->setText(blockdata);
                ui->listWidget->addItem("读取块内数据成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
            }else{disperrinf(status);}
        }else{disperrinf(status);}
    }else{disperrinf(status);}
}



void MainWindow::on_pushButton_piccwrite_clicked()
{
    if(!checkdllos()){return;}

    unsigned char serial[4];    //可写数组
    unsigned char area;         //操作扇区号
    unsigned char keyA1B0;      //AB密码认证方式
    unsigned char piccoldkey[6];//存放卡原始密码的数组
    unsigned char piccdata[16]; //存放块数据
    unsigned char status;       //返回

    int myblock=ui->spinBox->value();
    area=myblock/4;

    QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
    if(Key_str.length()==12 and checkinput(Key_str)){
        for(int i=0;i<6;i++){
            bool ok;
            piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
        }
    }else{
        QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
        return;
    }

    QChar ch;
    QString writinf = ui->textEdit_thisblock->toPlainText().trimmed();
    QString writinf4 = "";
    int m = 0;
    int n = 0;
    char s;
    for(int i=0; i<writinf.length() ; i++)
    {
        ch = writinf.at(i);
        s = writinf.at(i).toLatin1();
        if((('0' <= s) && (s <= '9')) || (('A' <= s) && (s <= 'F')) || (('a' <= s) && (s <= 'f')))
        {
            writinf4 += ch;
            n++;
            if(n==2){
                bool ok;
                piccdata[m++] = writinf4.toInt(&ok,16);
                writinf4 = "";
                n = 0;
                if(m>=16){
                    break;
                }
            }
        }
        else if(s == ' ') {

        }
        else
        {
            QMessageBox::critical(NULL, "提示", "写块数据输入错误,请输入正确的16进制数据!");
            //ui->textEdit_thisblock->setSelection(i,1);
            ui->textEdit_thisblock->setFocus();
            return;
        }
    }

    if(m<16)
    {
        QMessageBox::critical(NULL, "提示", "写块数据输入错误,请输入正确的16进制数据!");
        ui->textEdit_thisblock->setFocus();
        return;
    }

    status = mypiccrequest(serial);  //寻卡获取到卡号
    if(status == 0){
        unsigned int card10=serial[0]*256*256*256+serial[1]*256*256+serial[2]*256+serial[3];  //8H10D正码
        QString cardstr=QString::asprintf("%010d",card10);
        QString CardnoHex="";
        for(int i=0;i<4;i++){
            CardnoHex=CardnoHex+QString::asprintf("%02X", serial[i]);
        }

        status = mypiccauthkey1(serial,area,keyA1B0,piccoldkey);
        if(status == 0){
            status = mypiccwrite(myblock,piccdata);
            if(status == 0){
                mypcdbeep(30);
                ui->listWidget->addItem("写数据到块内成功,16进制卡号:"+CardnoHex+",转10进制卡号:"+cardstr);
            }else{disperrinf(status);}
        }else{disperrinf(status);}
    }else{disperrinf(status);}

}


void MainWindow::on_pushButton_piccwriteserial_clicked()
{
    if(!checkdllos()){return;}

    unsigned char serial[4];    //可写数组
    unsigned char area;         //操作扇区号
    unsigned char keyA1B0;      //AB密码认证方式
    unsigned char piccoldkey[6];//存放卡原始密码的数组
    unsigned char piccdata[16]; //存放块数据
    unsigned char status;       //返回

    unsigned char ctrlword = BLOCK0_EN  ;      //读写控制字
    keyA1B0 = ui->comboBox_2->currentIndex();   //密码认证类型,;大于0用A密码 ,等于0用B密码

    QString Key_str = ui->textEdit_oldkey->toPlainText().trimmed();
    if(Key_str.length()==12 and checkinput(Key_str)){
        for(int i=0;i<6;i++){
            bool ok;
            piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
        }
    }else{
        QMessageBox::critical(NULL, "提示","请输入12位16进制卡片认证密码!");
        return;
    }

    bool ok;
    unsigned int Cardno=ui->textEdit_uidno->toPlainText().toInt(&ok);
    if(ok){
        if(Cardno>4294967295){
            QMessageBox::critical(NULL, "提示", "UID号不可以>4294967295");
            return;
        }

        QString Cardnohex=("00000000"+DecimalToHex(Cardno)).right(8);
        unsigned char crc=0;
        for(int i=0;i<4;i++){
            bool ok;
            piccdata[i]=QString(Cardnohex.mid(i*2,2)).toInt(&ok,16);
            crc=crc ^piccdata[i];
        }
        piccdata[4]=crc;        //第4字节是校验位
        for(int i=5;i<16;i++){
            piccdata[i]=oldblock[i];
        }

        status = mypiccwriteserial(ctrlword,serial,keyA1B0,piccoldkey,piccdata);
        if(status == 0){
            mypcdbeep(30);
            ui->listWidget->addItem("UID卡号写入成功!");
        }else{disperrinf(status);}
    }else{
        QMessageBox::critical(NULL, "提示", "请输入10进制的UID号!");
        return;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vx_13822155058

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值