optical/EMBOS/Users/EmbFunc/security/password.c
2025-09-04 09:45:08 +08:00

307 lines
5.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}