QT调用动态库开发IC卡读写程序

本文介绍了如何使用C++通过DLL动态库操作MIFARE类型的IC卡,包括读取和写入数据到卡的特定扇区,以及修改卡片的A、B区密码。代码示例展示了读卡、写卡和密码修改的详细步骤,涉及权限控制和错误处理。
摘要由CSDN通过智能技术生成

 IC卡特点:

1IC卡的内部存储结构分为16个扇区,从第0区到第15区,每个扇区有独立的密码和权限控制字,可作为卡的密码和权限控制字专用独立的电子钱包,每个扇区有4个块,序号为第0块、第1块、第2块、第3块,每块16个字节,第3块是块,禁止在此存放数据。第0块、第1块、第2块可随意存放数据。但第0区的第0块已被固化了IC卡出厂信息,此块只能读出信息,不可更改。

调用DLL动态库代码:

   unsigned char result;
    QLibrary mylib("OUR_MIFARE.dll");
    if (!mylib.load())                //判断是否正确加载
    {
        QMessageBox::information(NULL, "提示", "动态库没装载!原因是动态库OUR_MIFARE.dll没放在生成exe文件相同目录下!");
        return;
    }

    pcdbeep mypcdbeep = (pcdbeep)mylib.resolve("pcdbeep");
    if (mypcdbeep == NULL)                   //是否成功连接上 idr_beep()函数
    {
        mylib.unload();
        QMessageBox::information(NULL, "提示", "请检查函数名是否正确!");
        return;

    }


    result = mypcdbeep(30);      //这里函数指针调用dll中的idr_beep() 函数
    mylib.unload();
    if(result > 0)
    {
        if(result == 23)
        {
            QMessageBox::information(NULL, "提示", "机器没连上或者驱动没下载");
        }
        else
        {
            QMessageBox::information(NULL, "提示", "错误代码:" + QString::number(result));
        };
    }

读出IC卡数据的代码:

void MainWindow::on_pushButton_3_clicked()//轻松读卡
{
    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;//返回
    unsigned char status1;
    unsigned char result;
    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->currentText().toUShort();
    keyA1B0 = 1;//用A密码
    QString Key_str = ui->lineEdit->text().trimmed();

    if(Key_str.length() < 12)
    {
        QMessageBox::information(NULL, "提示", "密码长度不够12位!");
        ui->lineEdit->setFocus();
        return;

    }

    char c;
    for (int var = 0; var < 12; ++var)
    {
        c = Key_str.at(var).toLatin1();
        if(!((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) || (('a' <= c) && (c <= 'f'))))
        {
          QMessageBox::information(NULL, "提示", "密码输入字符不正确!");
          ui->lineEdit->setSelection(var,1);
          ui->lineEdit->setFocus();
          return;
        }
    }


    bool ok;
    for(int i = 0; i < 6; i++)
    {
        picckey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
    }



    QLibrary mylib("OUR_MIFARE.dll");
    if (!mylib.load())                //判断是否正确加载
    {
        QMessageBox::information(NULL, "提示", "动态库没装载!原因是动态库OUR_MIFARE.dll没放在生成exe文件相同目录下!");
        return;
    }

    piccreadex mypiccreadex = (piccreadex)mylib.resolve("piccreadex");
    status = mypiccreadex(ctrlword,serial,area,keyA1B0,picckey,piccdata0_2);

    if(status == 0)
    {
        ui->lineEdit_2->setText(QString::asprintf("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X ",piccdata0_2[0],piccdata0_2[1],piccdata0_2[2],piccdata0_2[3],piccdata0_2[4],piccdata0_2[5],piccdata0_2[6],piccdata0_2[7],piccdata0_2[8],piccdata0_2[9],piccdata0_2[10],piccdata0_2[11],piccdata0_2[12],piccdata0_2[13],piccdata0_2[14],piccdata0_2[15]));
        ui->lineEdit_3->setText(QString::asprintf("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X ",piccdata0_2[16],piccdata0_2[17],piccdata0_2[18],piccdata0_2[19],piccdata0_2[20],piccdata0_2[21],piccdata0_2[22],piccdata0_2[23],piccdata0_2[24],piccdata0_2[25],piccdata0_2[26],piccdata0_2[27],piccdata0_2[28],piccdata0_2[29],piccdata0_2[30],piccdata0_2[31]));
        ui->lineEdit_4->setText(QString::asprintf("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X ",piccdata0_2[32],piccdata0_2[33],piccdata0_2[34],piccdata0_2[35],piccdata0_2[36],piccdata0_2[37],piccdata0_2[38],piccdata0_2[39],piccdata0_2[40],piccdata0_2[41],piccdata0_2[42],piccdata0_2[43],piccdata0_2[44],piccdata0_2[45],piccdata0_2[46],piccdata0_2[47]));

        piccread mypiccread = (piccread)mylib.resolve("piccread");
        status1 = mypiccread(area * 4 + 3,piccdata);
        if(status1 == 0)
        {
          ui->lineEdit_5->setText(QString::asprintf("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X ",piccdata[0],piccdata[1],piccdata[2],piccdata[3],piccdata[4],piccdata[5],piccdata0_2[6],piccdata[7],piccdata[8],piccdata[9],piccdata[10],piccdata[11],piccdata[12],piccdata[13],piccdata[14],piccdata[15]));

        }

        pcdbeep mypcdbeep = (pcdbeep)mylib.resolve("pcdbeep");
        if (mypcdbeep == NULL)                   //是否成功连接上 idr_beep()函数
        {
          mylib.unload();
          QMessageBox::information(NULL, "提示", "请检查函数名是否正确!");
          return;

        }

        result = mypcdbeep(30);      //这里函数指针调用dll中的idr_beep() 函数
        mylib.unload();

    }
    else if(status == 8)
    {
        ui->lineEdit_2->clear();
        ui->lineEdit_3->clear();
        ui->lineEdit_4->clear();
        QMessageBox::information(NULL, "提示", "寻卡错误,根本就没有卡在感应区");

    }
    else if(status == 12)
    {
        ui->lineEdit_2->clear();
        ui->lineEdit_3->clear();
        ui->lineEdit_4->clear();
        QMessageBox::information(NULL, "提示", "密码认证失败");

    }

}

 写入数据到IC卡的代码:

void MainWindow::on_pushButton_12_clicked()//轻松写卡
{  
    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;//返回
    unsigned char result;
    char s;
    //以下控制字含义:读块0、块1、块2,仅读指定序列号的卡,需要每次指定密码
    if (ui->radioButton->isChecked())
    {

        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY + NEEDHALT;

    }
    else
    {//内部密码
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;
    }



    area = ui->comboBox->currentText().toUShort();
    keyA1B0 = 1;//用A密码

    QString Key_str = ui->lineEdit->text().trimmed();

    if(Key_str.length() < 12)
    {
        QMessageBox::information(NULL, "提示", "密码长度不够12位!");
        ui->lineEdit->setFocus();
        return;

    }

    char c;
    for (int var = 0; var < 12; ++var)
    {
        c = Key_str.simplified().at(var).toLatin1();
        if(!((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) || (('a' <= c) && (c <= 'f'))))
        {
          QMessageBox::information(NULL, "提示", "密码输入字符不正确!");
          //ui->lineEdit->setSelection(var,1);
          ui->lineEdit->setSelection(var,1);
          ui->lineEdit->setFocus();
          return;
        }
    }

    bool ok;
    for(int i = 0; i < 6; i++)
    {
        picckey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
    }

    //第0块数据
    QChar ch;
    QString writinf = ui->lineEdit_2->text().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)
          {
              piccdata0_2[m++] = writinf1.toInt(&ok,16);
              writinf1 = "";
              n = 0;
              if(m>=16)
              {
                  break;
              }
          }
        }
        else if(s == ' ')
        {

        }
        else
        {
          QMessageBox::information(NULL, "提示", "写卡数据错误,请输入正确的16进制数据!");

          ui->lineEdit_2->setSelection(i,1);
          ui->lineEdit_2->setFocus();

          return;

        }
    }

    if(m<16)
    {
        QMessageBox::information(NULL, "提示", "第0块输入数据不足!");
        ui->lineEdit_2->setFocus();
        return;
    }


    //第1块数据
    writinf = ui->lineEdit_3->text().trimmed();
    QString writinf2 = "";
    m = 16;
    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')))
        {
          writinf2 += ch;//12 34
          n++;//2
          if(n==2)
          {
              piccdata0_2[m++] = writinf2.toInt(&ok,16);
              writinf2 = "";
              n = 0;
              if(m>=32)
              {
                  break;
              }
          }
        }
        else if(s == ' ')
        {

        }
        else
        {
          QMessageBox::information(NULL, "提示", "写卡数据错误,请输入正确的16进制数据!");
          qDebug() << i;
          ui->lineEdit_3->setSelection(i,1);
          ui->lineEdit_3->setFocus();
          return;
        }
    }
    if(m<16)
    {
        QMessageBox::information(NULL, "提示", "第1块输入数据不足!");
        ui->lineEdit_3->setFocus();
        return;
    }


    //第2块数据
    writinf = ui->lineEdit_4->text().trimmed();
    QString writinf3 = "";
    m = 32;
    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')))
        {
          writinf3 += ch;//12 34
          n++;//2
          if(n==2)
          {
              piccdata0_2[m++] = writinf3.toInt(&ok,16);
              writinf3 = "";
              n = 0;
              if(m>=48)
              {
                  break;
              }
          }
        }
        else if(s == ' ')
        {

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

        }
    }

    if(m<48)
    {
        QMessageBox::information(NULL, "提示", "第2块输入数据不足!");
        ui->lineEdit_4->setFocus();
        return;
    }

    QLibrary mylib("OUR_MIFARE.dll");
    if (!mylib.load())                //判断是否正确加载
    {
        QMessageBox::information(NULL, "提示", "动态库没装载!原因是动态库OUR_MIFARE.dll没放在生成exe文件相同目录下!");
        return;
    }

    piccwriteex mypiccwriteex = (piccwriteex)mylib.resolve("piccwriteex");
    status = mypiccwriteex(ctrlword,serial,area,keyA1B0,picckey,piccdata0_2);
    if(status == 0)
    {
        pcdbeep mypcdbeep = (pcdbeep)mylib.resolve("pcdbeep");
        if (mypcdbeep == NULL)                   //是否成功连接上 idr_beep()函数
        {
          mylib.unload();
          QMessageBox::information(NULL, "提示", "请检查函数名是否正确!");
          return;

        }
        result = mypcdbeep(30);      //这里函数指针调用dll中的idr_beep() 函数
        mylib.unload();
        QMessageBox::information(NULL, "提示", "写卡成功!");
    }
    else if(status == 8)
    {
        ui->lineEdit_2->clear();
        ui->lineEdit_3->clear();
        ui->lineEdit_4->clear();
        QMessageBox::information(NULL, "提示", "寻卡错误,根本就没有卡在感应区");
    }
    else if(status == 12)
    {
        ui->lineEdit_2->clear();
        ui->lineEdit_3->clear();
        ui->lineEdit_4->clear();
        QMessageBox::information(NULL, "提示", "密码认证失败");
    }
}

 修改A,B区密码:

void MainWindow::on_pushButton_14_clicked()
{
    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;//返回
    unsigned char result;
    if (ui->radioButton->isChecked())
    {
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY + NEEDHALT;
    }
    else
    {//内部密码
        ctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;
    }

    area = ui->comboBox->currentText().toUShort();
    keyA1B0 = 1;//用A密码
    QString Key_str = ui->lineEdit->text().trimmed();

    if(Key_str.length() < 12)
    {
        QMessageBox::information(NULL, "提示", "密码长度不够12位!");
        ui->lineEdit->setFocus();
        return;

    }

    char c;
    for (int var = 0; var < 12; ++var)
    {
        c = Key_str.simplified().at(var).toLatin1();
        if(!((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) || (('a' <= c) && (c <= 'f'))))
        {
          QMessageBox::information(NULL, "提示", "密码输入字符不正确!");
          ui->lineEdit->setSelection(var,1);
          ui->lineEdit->setFocus();
          return;
        }
    }

    bool ok;
    for(int i = 0; i < 6; i++)
    {
        piccoldkey[i]=QString(Key_str.mid(i*2,2)).toInt(&ok,16);
    }


    QChar ch;
    QString writinf = ui->lineEdit_5->text().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)
          {
              piccdata[m++] = writinf4.toInt(&ok,16);
              writinf4 = "";
              n = 0;
              if(m>=16)
              {
                  break;
              }
          }
        }
        else if(s == ' ')
        {

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

        }
    }

    if(m<16)
    {
        QMessageBox::information(NULL, "提示", "第3块输入数据不足!");
        ui->lineEdit_5->setFocus();
        return;
    }

    QLibrary mylib("OUR_MIFARE.dll");
    if (!mylib.load())                //判断是否正确加载
    {
        QMessageBox::information(NULL, "提示", "动态库没装载!原因是动态库OUR_MIFARE.dll没放在生成exe文件相同目录下!");
        return;
    }
    piccchangesinglekeyex mypiccchangesinglekeyex = (piccchangesinglekeyex)mylib.resolve("piccchangesinglekeyex");
    status = mypiccchangesinglekeyex(ctrlword,serial,area,keyA1B0,piccoldkey,piccdata);
    QMessageBox::warning(this, "警告", "你确定修改密码控制块的数据吗 ?此数据块如果改写错误,数据卡将会被限制", QMessageBox::Ok, QMessageBox::Cancel);
    if(status == 0)
    {
        QMessageBox::information(NULL, "提示", "操作成功,写卡数据有效!");
        pcdbeep mypcdbeep = (pcdbeep)mylib.resolve("pcdbeep");
        if (mypcdbeep == NULL)                   //是否成功连接上 idr_beep()函数
        {
          mylib.unload();
          QMessageBox::information(NULL, "提示", "请检查函数名是否正确!");
          return;

        }
        result = mypcdbeep(30);      //这里函数指针调用dll中的idr_beep() 函数
        mylib.unload();

    }
    else if(status == 8)
    {
        QMessageBox::information(NULL, "提示", "寻卡错误,根本就没有卡在感应区");

    }
    else if(status == 12)
    {
        QMessageBox::information(NULL, "提示", "密码认证失败");
    }

}

有问题请留言,不忙的时候会看。

若对你有帮助,点赞收藏,经常更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值