#include "password.h" #include "crc8.h" //------------------------------------------------------------------------------- // 密码串字符集 #define CHAR_TAB_LEN 32 #define CHAR_BITS 5 #define PSWD_BIT_LEN (PSWDSTR_LEN*CHAR_BITS) #define PSWD_BYTE_LEN ((PSWD_BIT_LEN+CHAR_BITS-1)/8) #define CHAR32MASK 0x1F #define XOR_VAL 0x59 static const char g_charTable[CHAR_TAB_LEN] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', }; #define CLINET_NUM 3 // 客户个数 // 存储序列表 static const u8 g_saveSWTab[CLINET_NUM+1][PSWDSTR_LEN] = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }, // 默认 { 4, 9, 17, 5, 10, 14, 16, 6, 18, 3, 20, 11, 1, 13, 19, 15, 2, 7, 12, 8 }, // 宝盈 { 13, 7, 12, 4, 6, 19, 3, 10, 17, 20, 11, 18, 15, 5, 14, 2, 8, 1, 9, 16 }, // 上工 { 10, 4, 11, 8, 16, 12, 5, 9, 17, 19, 7, 14, 20, 3, 13, 1, 15, 2, 6, 18 }, // 再登 }; //------------------------------------------------------------------------------- typedef union { u8 pswdbin[PSWD_BYTE_LEN]; struct { u8 check; // 校验码 s32 totalTime; // 累计改变时间 s16 thisTime; // 本次改变时间 u32 cpuId; // CPU ID u8 clientId; // 客户ID u8 moveBit; // 移位 } __attribute__ ((packed)) pswdstruct; struct { u8 check; // 校验码 u8 datbuff[12]; } __attribute__ ((packed)) pswdckdat; } Password; //------------------------------------------------------------------------------- // 得到某个位的值 int GetBitVal(u8 * buff, int bitidx) { int i; u8 mod = 0x01; u8 num = bitidx % 8; buff += bitidx / 8; for (i = 0; i < num; i++) { mod *= 2; } if ((*buff & mod) != 0) { return 1; } else { return 0; } } // 设置某个位的值 void SetBitVal(u8 * buff, int bitidx, int bitval) { int i; u8 mod = 0x01; u8 num = bitidx % 8; buff += bitidx / 8; for (i = 0; i < num; i++) { mod *= 2; } if (bitval != 0) { *buff |= mod; } else { *buff &= (~mod); } } // 循环移位 // movenum > 0, 左移 // movenum < 0, 右移 void CyclicShift(u8 * buff, int bitlen, int movenum) { int mvdir; if (buff == 0 || bitlen <= 1 || movenum == 0) { return; } if (movenum < 0) // 右移 { mvdir = -1; } else // 左移 { mvdir = 1; } movenum *= mvdir; movenum %= bitlen; int bitidx = 0; int nbidx; int bitval, tmpval; // 取出 bitidx == 0 的位 bitval = GetBitVal(buff, bitidx); do { // 计算新的位置 if (mvdir < 0) // 右移 { nbidx = bitidx - movenum; if (nbidx < 0) { nbidx += bitlen; } } else // 左移 { nbidx = bitidx + movenum; if (nbidx >= bitlen) { nbidx -= bitlen; } } // 先取出 nbidx 原来的位 tmpval = GetBitVal(buff, nbidx); // 将 bitidx 的位写入到 nbidx 的位置 SetBitVal(buff, nbidx, bitval); bitidx = nbidx; bitval = tmpval; }while(bitidx != 0); } //------------------------------------------------------------------------------- // 解密 int DecodePswdString(PswdCtrl * pCtrl, char * pswdStr, u8 clientId) { char pslist[PSWDSTR_LEN]; // 交换后的 32 进制数据串 Password pswd; u8 moveBit; if (pCtrl == 0 || pswdStr == 0) { return -1; } memset(pCtrl, 0, sizeof(PswdCtrl)); if (clientId <= 0 || clientId > CLINET_NUM) { return -1; } // 1. 得到密码串后,按照客户序列反向解析,得到正确序列的32进制数据串。 { int i, idx; for (i = 0; i < PSWDSTR_LEN; i++) { idx = g_saveSWTab[clientId][i] - 1; pslist[i] = pswdStr[idx]; } } // 2. 根据32进制数据串,得到100位的二进制数据串 { int i, j; u8 buff32[PSWDSTR_LEN]; // 32进制数据的二进制表示 for (i = 0; i < PSWDSTR_LEN; i++) { char ch32 = pslist[i]; for (j = 0; j < CHAR_TAB_LEN; j++) { if (ch32 == g_charTable[j]) { break; } } if (j >= CHAR_TAB_LEN) { return -1; } buff32[i] = j; } memset(&pswd, 0, sizeof(Password)); for (i = PSWDSTR_LEN-1; i >= 0; i--) { u8 bin = buff32[i]; bin &= CHAR32MASK; for (j = PSWD_BYTE_LEN-1; j > 0; j--) // 移位 5 位 { pswd.pswdbin[j] <<= CHAR_BITS; pswd.pswdbin[j] |= (pswd.pswdbin[j-1] >> (8-CHAR_BITS)); } pswd.pswdbin[0] <<= CHAR_BITS; pswd.pswdbin[0] |= bin; } } // 3.对二进制字符串做异或操作。 { int i; for (i = 0; i < PSWD_BYTE_LEN; i++) { pswd.pswdbin[i] ^= XOR_VAL; } pswd.pswdbin[PSWD_BYTE_LEN-1] &= 0x0f; } // 4. 按照移位规则,反向移位加密信息数据段后,得到密码信息数据段。 { int movenum, idx; pswd.pswdstruct.moveBit &= 0x0f; // 移位数据段 moveBit = pswd.pswdstruct.moveBit; // 移位次数索引 movenum = g_saveSWTab[clientId][moveBit]; // 移位次数 idx = 0x10; while (idx < PSWDSTR_LEN && (movenum == 5 || movenum == 10 || movenum == 15 || movenum == 20)) { movenum = g_saveSWTab[clientId][idx]; idx++; } if (idx == PSWDSTR_LEN || (movenum == 5 || movenum == 10 || movenum == 15 || movenum == 20) || movenum <= 0 || movenum > PSWDSTR_LEN) { return -1; } if ((moveBit & 0x01) != 0) // 解密,循环移动 { // 循环左移 } else { // 循环右移 movenum *= -1; } CyclicShift(pswd.pswdbin, PSWD_BIT_LEN-4, movenum); } // 5. 按照校验算法,检验信息数据段的正确性。 { u8 crc = CalcCrc8(pswd.pswdckdat.datbuff, sizeof(Password)-1); if (crc != pswd.pswdstruct.check) { return -1; } pCtrl->clientId = pswd.pswdstruct.clientId; pCtrl->cpuId = pswd.pswdstruct.cpuId; pCtrl->thishours = pswd.pswdstruct.thisTime / TIME_MUTI; pCtrl->totalhours = pswd.pswdstruct.totalTime / TIME_MUTI; pCtrl->nexttotaltime = (pCtrl->thishours+pCtrl->totalhours)*TIME_MUTI + (int)(pswd.pswdstruct.thisTime+pswd.pswdstruct.totalTime)%TIME_MUTI; pCtrl->totaltime = pswd.pswdstruct.totalTime; pCtrl->thistime = pswd.pswdstruct.thisTime; } /* 6.验证客户识别码和主板识别码是否符合当前设备。 7.验证上次加密累计时间是否和板卡保存的一致(按小时数验证)。 8.将新的改变时间加到当前计数时间,并写入计数区域。 9.保存密码串到记录区域。 */ return 0; }