找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 640|回复: 0
收起左侧

STM32F103配合Win上位机实现加解密(类似U盾原理)

[复制链接]
ID:187303 发表于 2025-10-16 09:41 | 显示全部楼层 |阅读模式
上位机:远程解锁加密工具 v1.7.exe

远程解锁加密工具 v1.7.png


下位机代码:

  1. #include "stm32f10x.h"
  2. #include "stm32f10x_usart.h"
  3. #include "stm32f10x_iwdg.h"
  4. #include "GPIO.H"//要使用GPIO中间件的话记得包含头文件
  5. #include "USART.H"
  6. #include "NVIC.H"
  7. #include "IWDG.H"
  8. #include "AES.h"
  9. #include "stdio.h"
  10. #include "stdlib.h"
  11. #include <string.h>
  12. #include "core_cm3.h"

  13. void STM32_USART_RX_interrupt(void);
  14. #define LED0 PCout(13)// PB5
  15. //初始化PB5和PE5为输出口.并使能这两个口的时钟
  16. //LED IO初始化
  17. void LED_Init(void)
  18. {
  19.     GPIO_InitTypeDef  GPIO_InitStructure;

  20.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);    //使能PB,PE端口时钟

  21.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;               //LED0-->PB.5 端口配置
  22.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //推挽输出
  23.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //IO口速度为50MHz
  24.     GPIO_Init(GPIOC, &GPIO_InitStructure);                   //根据设定参数初始化GPIOB.5
  25. }

  26. /******************************************************************************
  27. 函数名称:读取芯片唯一ID码
  28. 备    注:
  29. ******************************************************************************/
  30. unsigned char BFLASH[12];   //存放芯片ID的临时变量

  31. void Get_ChipID(void)
  32. {
  33.     u32 temp0, temp1, temp2;
  34.     temp0 = *(__IO u32 *)(0x1FFFF7E8);   //产品唯一身份标识寄存器(96位)
  35.     temp1 = *(__IO u32 *)(0x1FFFF7EC);
  36.     temp2 = *(__IO u32 *)(0x1FFFF7F0);

  37.     //ID码地址: 0x1FFFF7E8   0x1FFFF7EC  0x1FFFF7F0 ,只需要读取这个地址中的数据就可以了。

  38.     BFLASH[0] = (u8)(temp0 & 0x000000FF);
  39.     BFLASH[1] = (u8)((temp0 & 0x0000FF00) >> 8);
  40.     BFLASH[2] = (u8)((temp0 & 0x00FF0000) >> 16);
  41.     BFLASH[3] = (u8)((temp0 & 0xFF000000) >> 24);
  42.     BFLASH[4] = (u8)(temp1 & 0x000000FF);
  43.     BFLASH[5] = (u8)((temp1 & 0x0000FF00) >> 8);
  44.     BFLASH[6] = (u8)((temp1 & 0x00FF0000) >> 16);
  45.     BFLASH[7] = (u8)((temp1 & 0xFF000000) >> 24);
  46.     BFLASH[8] = (u8)(temp2 & 0x000000FF);
  47.     BFLASH[9] = (u8)((temp2 & 0x0000FF00) >> 8);
  48.     BFLASH[10] = (u8)((temp2 & 0x00FF0000) >> 16);
  49.     BFLASH[11] = (u8)((temp2 & 0xFF000000) >> 24);
  50. }

  51. void SoftReset(void)
  52. {
  53.     __set_FAULTMASK(1);      // 关闭所有中端
  54.     NVIC_SystemReset();// 复位
  55. }

  56. void Delay(unsigned int i)
  57. {
  58.     unsigned int j;
  59.     for(; i > 0; i--)
  60.         for(j = 0; j < 1000; j++);
  61. }

  62. #define STM32CLI()      __set_PRIMASK(1)   //关闭总中断
  63. #define STM32SEI()      __set_PRIMASK(0)   //开放总中断  

  64. void STM32_USART_RX_interrupt(void)
  65. {
  66.     u8 i, data[42];
  67.     char hex[128];
  68.     char *p_hex = hex;
  69.     char aesKey[16];//加解密的密钥,注意:此算法只适用于AES16位密钥加解密,不适用于32位密钥加解密
  70.     //该AES算法加密方式为:AES-128bit/ECB/PKCS5Padding
  71.     char expressText[64];  //存放待加密的明文数据,具体缓存大小根据用户待加密数据长度自己任意修改
  72.     char cipherText[64];//存放已加密的密文数据,具体缓存大小根据用户解密后的数据长度自己任意修改

  73.     char unLockDT[3];//解锁日期(当日有效)
  74.     char LockDT[3];//锁定日期()
  75.     char MachID[12];//机器码
  76.     char AdminTEL[5];//管理者手机号

  77.     if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) == SET) //溢出
  78.     {
  79.         USART_ClearFlag(USART1, USART_FLAG_ORE); //读SR
  80.         USART_ReceiveData(USART1); //读DR
  81.     }
  82.     if (USART_GetFlagStatus(USART1, USART_FLAG_PE) != RESET)
  83.     {
  84.         USART_ReceiveData(USART1);
  85.         USART_ClearFlag(USART1, USART_FLAG_PE);
  86.     }

  87.     if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
  88.     {
  89.         USART_ReceiveData(USART1);
  90.         USART_ClearFlag(USART1, USART_FLAG_ORE);
  91.     }

  92.     if (USART_GetFlagStatus(USART1, USART_FLAG_FE) != RESET)
  93.     {
  94.         USART_ReceiveData(USART1);
  95.         USART_ClearFlag(USART1, USART_FLAG_FE);
  96.     }

  97.     //*
  98.     for (i = 0; i < 42; i++)
  99.     {
  100.         data[i] = DK_USART_WAIT_RXBYTE(1); //读取接收到的数据
  101.     }
  102.     //*/

  103.     /*
  104.     指令格式:
  105.     同步字2+序号1+密钥32+解锁日期3+客户机器码24+锁定日期3+管理者手机号20=85位
  106.     */
  107.     //*
  108.     if ((data[0] == 0xF3) & (data[1] == 0x3A)) //同步字正确
  109.     {
  110.         switch (data[2]) //第1字节
  111.         {
  112.         case 0x01://取密钥
  113.         {
  114.             //*
  115.             //-----------------------------------------------------------------
  116.             memset(aesKey , 0 , 16);//清零
  117.             for (i = 0; i < 16; i++)
  118.             {
  119.                 aesKey[i] = data[i + 3]; //得到密钥
  120.             }
  121.             //-----------------------------------------------------------------
  122.             memset(unLockDT , 0 , 3);//清零
  123.             for (i = 0; i < 3; i++)
  124.             {
  125.                 unLockDT[i] = data[i + 19]; //解锁日期(当日有效)
  126.             }
  127.             //-----------------------------------------------------------------
  128.             memset(MachID , 0 , 12);//清零
  129.             for (i = 0; i < 12; i++)
  130.             {
  131.                 MachID[i] = data[i + 22]; //机器码
  132.             }
  133.             //-----------------------------------------------------------------
  134.             memset(LockDT , 0 , 3);//清零
  135.             for (i = 0; i < 3; i++)
  136.             {
  137.                 LockDT[i] = data[i + 34]; //锁定日期()
  138.             }
  139.             //-----------------------------------------------------------------
  140.             memset(AdminTEL , 0 , 5);//清零
  141.             for (i = 0; i < 5; i++)
  142.             {
  143.                 AdminTEL[i] = data[i + 37]; //管理者手机号
  144.             }
  145.             //-----------------------------------------------------------------

  146.             //------------------------------------------------------------------------
  147.             //*加密过程:测试通过
  148.             memset(expressText , 0 , 64);
  149.             memset(cipherText , 0 , 64);

  150.             //------------------------------------------------------------------------
  151.             for (i = 0; i < 39; i++)
  152.             {
  153.                 expressText[i] = data[i + 3]; //
  154.             }

  155.             BFH_Encrypt(expressText  , cipherText , aesKey);    //使用密钥aesKey把expressText加密为cipherText
  156.             StrToHex(cipherText, p_hex);//把cipherText转换为16进制字符串hex
  157.             //------------------------------------------------------------------------

  158.             DK_USART_PUTS(DK_USART1, hex);//返回加密数据
  159.             //DK_USART_PUTS(DK_USART1, "\r\n");
  160.             //------------------------------------------------------------------------


  161.             //------------------------------------------------------------------------
  162.             /*解密过程:测试通过
  163.             memset(expressText , 0 , 64);
  164.             memset(cipherText , 0 , 64);

  165.             //等待解密的字符串不完整将不会解密成功
  166.                         u8 *ihex;//使用指针,可以动态赋值
  167.             ihex = "7677685A504563592B54503047644E417564502B6530714C4B523771746B5650435233725142344E446477417678476B5541536F71723376682F49636555692B";
  168.             HexToStr(ihex, cipherText);//ihex值为16进制字符串,需要先转换成普通字符串再进行解密

  169.             BFH_Decrypt(expressText , cipherText , aesKey);//使用密钥aesKey把cipherText解密为expressText

  170.             StrToHex(expressText, p_hex);//把expressText转换为16进制字符串hex
  171.             //------------------------------------------------------------------------
  172.                         u8 IDBlock[25];
  173.             memset(IDBlock , 0 , 25);
  174.             StrCopy(IDBlock, hex, 32, 6);//解锁日期
  175.             DK_USART_PUTS(DK_USART1, "解锁日期=");
  176.             DK_USART_PUTS(DK_USART1, IDBlock);
  177.             DK_USART_PUTS(DK_USART1, "\r\n");

  178.             memset(IDBlock , 0 , 25);
  179.             StrCopy(IDBlock, hex, 38, 24);//机器码
  180.             DK_USART_PUTS(DK_USART1, "机器码=");
  181.             DK_USART_PUTS(DK_USART1, IDBlock);
  182.             DK_USART_PUTS(DK_USART1, "\r\n");


  183.             memset(IDBlock , 0 , 25);
  184.             StrCopy(IDBlock, hex, 62, 6);//锁定日期
  185.             DK_USART_PUTS(DK_USART1, "锁定日期=");
  186.             DK_USART_PUTS(DK_USART1, IDBlock);
  187.             DK_USART_PUTS(DK_USART1, "\r\n");

  188.             memset(IDBlock , 0 , 25);
  189.             StrCopy(IDBlock, hex, 68, 20);//管理者手机号
  190.             DK_USART_PUTS(DK_USART1, "管理者手机号=");
  191.             DK_USART_PUTS(DK_USART1, IDBlock);
  192.             DK_USART_PUTS(DK_USART1, "\r\n");
  193.             //-----------------------------------------------------------
  194.                         //*/
  195.             /*解密过程:测试通过*/
  196.             /*
  197.             memset(expressText , 0 , 64);
  198.             memset(cipherText , 0 , 64);

  199.             // memcpy(aesKey , "48FF6A06756754483041126720170926" , 16);  //AES加密密钥,16字节(128bit)

  200.             /*等解密的字符串不完整将不会解密成功*/
  201.             /*
  202.             char *ihex;//使用指针,可以动态赋值
  203.             ihex = "48FF6A06756754483041126720170926";
  204.             HexToStr(ihex, aesKey);//ihex值为16进制字符串,需要先转换成普通字符串作为密钥

  205.             ihex = "7677685A504563592B54503047644E417564502B6530714C4B523771746B5650435233725142344E446477417678476B5541536F71723376682F49636555692B";
  206.             HexToStr(ihex, cipherText);//ihex值为16进制字符串,需要先转换成普通字符串再进行解密

  207.             BFH_Decrypt(expressText , cipherText , aesKey);//使用密钥aesKey把cipherText解密为expressText

  208.             //------------------------------------------------------------------------

  209.             memset(unLockDT , 0 , 3);
  210.             StrCopy(unLockDT, expressText, 16, 3);//解锁日期(当日有效)

  211.             memset(MachID , 0 , 12);
  212.             StrCopy(MachID, expressText, 19, 12);//机器码

  213.             memset(LockDT , 0 , 3);
  214.             StrCopy(LockDT, expressText, 31, 3);//锁定日期

  215.             memset(AdminTEL , 0 , 5);
  216.             StrCopy(AdminTEL, expressText, 34, 5);//管理者手机号

  217.             //CAN_Return(0x31, HDID, AdminTEL[0], AdminTEL[1], AdminTEL[2], AdminTEL[3], AdminTEL[4], 0xDD);
  218.             //下面是对解密后的明文expressText解析内容:
  219.             //0-5:解锁有效日期、6-29:机器码、30-36:再次锁定日期
  220.             /*
  221.             1、机器码是否正确
  222.             2、检测解锁有效日期、锁定日期是否有效
  223.             3、再次锁定有效期。
  224.             */
  225.             //-------------------------------------
  226.             /*
  227.             u8 Fixed = 0;
  228.             u8 AdminMem[5] = {0x39, 0x78, 0x82, 0x80, 0x80};
  229.             u16 TBS = 0;
  230.             LED0 = 0;

  231.             for (i = 0; i < 4; i++)
  232.             {
  233.             if (AdminTEL[i] != AdminMem[i])
  234.             {
  235.             Fixed = 1;

  236.             break;
  237.             }
  238.             }

  239.             if (!Fixed)//解锁手机号正确
  240.             {
  241.             for (i = 0; i < 11; i++)
  242.             {
  243.             if (MachID[i] != BFLASH[i])
  244.             {
  245.             Fixed = 1;

  246.             break;
  247.             }
  248.             }
  249.             if (!Fixed)//ID正确
  250.             {
  251.             if (TBS == 1709)//解锁日期有效
  252.             {
  253.             if (TBS == 1712)//锁定日期有效
  254.             {
  255.                 //执行锁定日期更新
  256.                 LED0 = 1;
  257.             }
  258.             }
  259.             }
  260.             }
  261.             */

  262.             break;
  263.         }
  264.         }
  265.     }
  266.     //*/
  267. }

  268. int main(void)//利用库函数来实现
  269. {
  270.     SystemInit();
  271.     DK_USART_Init(115200, 1); //初始化USART1
  272.     DK_NVIC_Init(1);//选择NVIC_PriorityGroup_4,4位全部为占先式优先级,要实现中断必须先初始化NVIC
  273.     DK_NVIC_IRQ_Set(USART1_IRQn, 0, 0, ENABLE); //要实现外设中断,必须先设置外设的优先级
  274.     DK_USART_OPen_INT(1);//打开USART1的接收中断,然后再打开外设的中断功能
  275.     LED_Init();              //LED端口初始化

  276.     while(1)
  277.     {
  278.         Delay(10000);
  279.         LED0 = !LED0;
  280.     }
  281. }
复制代码



单片机代码与上位机exe文件下载:
STM32F103配合Win上位机实现加解密(类似U盾原理).7z (377.68 KB, 下载次数: 0)

评分

参与人数 1黑币 +80 收起 理由
admin + 80 共享资料的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表