307 lines
5.9 KiB
C
307 lines
5.9 KiB
C
|
||
#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;
|
||
}
|
||
|
||
|
||
|
||
|