应用程序本身已经完成,但我没有找到一个好的方法来存储和检查密码。所有东西都应该本地存储(没有检查网络数据库或其他任何内容)。如何定义一个解锁我的应用程序的密码,同时使其灵活(能够在不重新编译应用程序的情况下更改密码)?如何以安全的方式实现这一点?
存储密码的安全散列值,无需可逆。
当用户输入密码时,您可以使用相同的算法对其进行哈希处理,并检查是否与哈希匹配。
因为您从未存储实际密码,所以它是安全的。
我建议使用类似于 PBKDF2 的密钥拉伸算法。.NET 可以使用 Rfc2898DeriveBytes
支持此功能,或者您可以使用System.Web.Helpers.Crypto
。
此外,您使用的密码应该足够长(至少12个字符,但更长更好),并带有额外的字符串盐,以防止攻击者使用彩虹表攻击。
在配置文件中存储密码的标准方法是使用强哈希算法。请阅读如何在Winforms应用程序中存储密码?以及维基百科文章https://en.wikipedia.org/wiki/Cryptographic_hash_function
我不同意Brian的观点,因为目前在任何数据库中存储密码的标准方法是使用随机生成的值对密码进行“加盐”(详见Wikipedia),并将散列值和盐存储在您的“数据库”中(参见备注)。盐不是一个秘密,所以可以明文存储。每当用户输入密码时,您从文件中读取盐,将其应用于输入的密码,然后应用您选择的哈希算法。接下来,将结果与存储的哈希值进行比较。如果它们匹配,则用户已通过身份验证。想要了解为什么“仅仅”哈希密码是不够安全的,请参阅这篇有趣的文章:How NOT to store passwords! 想要在C#中实现加盐和哈希过程的教程,请参考:C# Salting & Hashing Passwords
您还可以在这里找到一种不错的方法:https://dev59.com/_mcs5IYBdhLWcg3wrl4Z#12657970
为了快速参考,以下是伪代码中的流程:
首先是密码存储:
//get user input
username = GetUserName
password = GetPassword
//generate random salt
salt = GetRandomValue
//combine password and salt and apply hash
hashedPassword = Hash(password + salt)
//store hash value and salt in database
AddToDatabase(username, hashedPassword, salt)
用户登录:
//get user input
username = GetUserName
password = GetPassword
//read salt from database
salt = GetSaltFromDatabase(username)
//combine password and salt and apply hash
hashedPassword = Hash(password + salt)
//compare hash to stored hash value
correctHash = GetHashFromDatabase(username)
if (hashedPassword == correctHash) then
passwordIsCorrect = True
else
passwordIsCorrect = False
end if
备注:
您可以将密钥和密码的哈希值存储在某个本地文件中。当用户输入密钥和密码时,您会获取这些值的哈希值并将其与文件中的哈希值进行比较。
使用SectionInformation
类中的ProtectSection()
和UnprotectSection()
方法相对容易。请参阅本文:
http://www.davidgiard.com/2012/06/05/EncryptingAndDecryptingApplicationConfigSections.aspx
http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.protectsection.aspx