系统登录时会进行密码的签名校验,在创建新用户时会将加密密码的Hash值存储在库中,再次登录时会计算输入密码加密后的Hash值与库内存储的Hash值进行比对,若不同则直接返回密码存储完整性检查失败
但比较奇怪的是正常来说刚刚新建用户的密码肯定没被篡改,并且用户密码的Hash的存储位置不易被篡改,但偏偏会偶现新建用户登录后直接报错的显示,经过多次新建用户登录工具测试发现改问题的出现与用户无关,与登录的工具或是使用登录框的方式无关,仅与密码本身有关,问题如下:
新建用户,用户密码为Opt@1234,登录会存在新密码存储完整性检查失败问题,使用其他密码则登录正常,看来问题出在这个特殊密码Opt@1234上。
针对密码完整性校验出现错误可能存在的原因有以下三种情况:
- 密码完整性校验出现错误
- 密码在登录框中输入后再计算其Hash值时出现错误
- 创建密码时存储在库中的Hash值出现错误
针对第一种情况查找校验签名部分代码如下:
char password_digest[32];
if (!pass_digest(password, sizeof(password), password_digest))
{
ret = false;
}
else
{
if (ACE_OS::memcmp(pad15, password_digest, sizeof(pad15)) != 0)
{
ret = false;
}
else
{
ret = true;
}
}
校验签名的代码看上无问题,否则校验其他密码的签名时也会存在问题,同时在该接口中调用了pcs_digest计算签名的接口,因此情况2也排除,所以需要针对情况3进行深入研究,确认是否是在新增用户时存储加密密码的签名时出现了问题,所以在pcs_digest增加打印。
然后使用登录框时进行打印可以看到如下内容:
可以看到pad15存储的内容不对,后面全是0与直接使用pcs_digest算出的签名不同,因此断定是存储签名不对,找到存储签名的代码如下:
char digest[32];
ACE_OS::memset(digest,0,sizeof(digest));
pass_digest(password_en,sizeof(password),digest);
string_cpy(pad15,digest,32)
发现问题很有可能出在string_cpy接口上,查看string_cpy接口:
void string_cpy(char * a, const char *b, ULong len)
{
if (b == NULL || a == NULL) return;
Long index = 0;
while( index < len)
{
a[index] = b[index];
if (b[index] == '\0') return;
index++;
}
}
经过查询"\0"的ASCII码为0,真相大白,使用string_cpy字符串接口拷贝时当遇到0时不再拷贝,所以使用string_cpy拷贝签名时会出现问题,应当使用memcpy,修改memcpy后问题解决。