在我目前的一个项目中,我正在使用单用户身份验证系统。我说“单用户”,因为我没有计划在同一个Windows帐户上为多个用户开展这项工作(仅仅因为它不是我想做的事情)。
当用户启动应用程序时,会向他们显示身份验证屏幕。该验证屏幕使用图像(即,点击图像中的3个特定点),用户名(标准编辑框)和图像选择(允许它们选择他们希望使用的图像的下拉菜单)。图像选项,用户名和点击图像的点数必须与用户在设置密码时指定的内容相匹配。
所有3个结果都合并为一个字符串,然后使用Soap.EncdDecd.EncodeString
方法进行编码。然后使用SHA-512进行散列。最后,它使用DES加密。然后将此值与设置密码时创建的值进行比较。如果匹配,则授予他们访问权限。如果不是,则拒绝访问。我计划在应用程序的其他位置使用SHA512值(例如“主密码”,用于在主应用程序中使用各种不同的模块进行授权)。
在一个示例中,初始字符串的长度为29个字符,SOAP编码的字符串大约为40个字符,SHA-512字符串为128个字符,DES值为344个字符。由于我不使用大量字符串,所以它实际上非常快。 SOAP被用作非常基本的混淆,而不是安全措施。
我担心的是第一部分(普通字符串和SOAP)可能是弱点。基本字符串不会给他们一些他们可以输入并被授予访问权限的东西,但它会给他们“图像点击坐标”,以及用户名和图像选择,这可能允许他们访问应用程序。 SOAP字符串可以很容易地解码。
强化身份验证的第一部分以尝试避免从内存直接撕掉这些值的最佳方法是什么?我是否应该关注潜在的剥削者或攻击者以这种方式阅读价值观?
作为与同一主题直接相关的其他问题;
在初始设置期间存储用户创建的密码哈希的最佳方法是什么?
我目前正在运行TIniFile.SectionExists
方法,因为我还没有找到更优雅的东西。这是我缺乏知识的一个领域。我需要跨会话存储密码“hash”(因此使用内存流不是一个选项),但我需要确保安全性足够好,以至于任何脚本小子都无法彻底破解。
更重要的是我是否应该关注,以及我所做的编码,散列和加密是否足够。我开发的图片密码系统已经是一个很好的基础,可以阻止传统的“我知道你的基于文本的密码是什么,所以现在我在你的系统中”攻击,但我很担心更多从内存中读取的技术攻击。
答案 0 :(得分:5)
使用SHA-512,从哈希值中检索初始内容是不可行的(至少在20年的计算能力和地球电能之前)。
我甚至认为使用DES不是强制性的,并且增加了复杂性。当然,你可以使用这种缓慢的过程来使蛮力或基于字典的攻击更难(因为它会使每次尝试变慢)。更常见的是不使用DES,而是多次调用SHA-512(例如1000次)。在这种情况下,速度可能是你的敌人:快速进程将更容易攻击。
您可能要做的是在初始值中添加所谓的“盐”。请参阅this Wikipedia article。
“salt”可以在代码中修复,也可以存储在密码中。
那是:
Hash := SHA512(Salt+Coordinates+UserName+Password);
最后的建议:
例如,这里是如何“清理”你的记忆(但它可能比这复杂得多):
Content := Salt+Coordinates+UserName+Password;
for i := 1 to length(Coordinates) do
Coordinates[i] := ' ';
for i := 1 to length(UserName) do
UserName[i] := ' ';
for i := 1 to length(Password) do
Password[i] := ' ';
Hash := SHA512(Content);
for i := 1 to length(Content) do
Content[i] := ' ';
for i := 1 to 1000 do
Hash := SHA512(Hash);
当涉及到安全问题时,不要试图重新发明轮子:这是一件困难的事情,你最好依靠数学证明(如SHA-512)和经验丰富的技术(如盐,挑战......) )。
对于某些身份验证方案示例,请查看main in the middle。它肯定不完美,但它试图实施一些最佳实践。