Security 使用登录名保护密码
我有一个关于使用登录名保护密码的问题Security 使用登录名保护密码,security,encryption,hash,passwords,Security,Encryption,Hash,Passwords,我有一个关于使用登录名保护密码的问题 您可以使用共享salt对登录名进行加密,然后使用BCrypt对其进行散列 然后获取原始的纯文本登录名,并将其用作密钥,用AES加密密码。然后用一种独特的盐腌制结果,最后用BCrypt散列 创建帐户时,用户的显示名称设置为其用户ID(整数),而不是其登录名。用户可以在以后更改它,除非它不能与其他任何人的显示名匹配,或者与他们的登录名的不区分大小写的比较过于接近 我的问题是,如果数据库被破坏,这是否会使恢复密码比存储纯文本用户名和唯一的salt和BRcypted
这个过程似乎非常复杂。实际上,您正在向存储的散列(散列密码的过程)添加服务器端机密。只要程序保密,这确实会增加安全性。换句话说,如果攻击者只有对数据库的读取权限(SQL注入),那么您就有了优势,只要他在服务器上拥有权限并知道代码,就根本没有优势 不过,有一种更简单、更安全的方法可以获得这种优势。只需使用随机salt计算BCrypt哈希(大多数实现都会这样做),然后使用服务器端密钥(例如AES)加密此哈希值。该键不应从其他参数中派生,而应使用足够长且随机的键 我试着在我的教程中解释原因,也许你想看看 编辑: 我现在明白了,您希望像处理第二个密码一样处理登录名,并且不会将其存储为明文,而是只存储带有全局“salt”的BCrypt散列 假设您愿意花费1秒的CPU时间进行密码哈希。在您的方案中,您必须将其拆分为半秒以散列登录名,半秒以散列密码。攻击者必须首先强制输入登录名,然后在第二步强制输入密码
这意味着您需要花半秒钟的时间来输入非常弱的密码(登录名),然后再花半秒钟的时间输入普通密码。与为普通(希望是强密码)投入1秒相比,您可能正在降低安全性,无论如何,我看不到任何优势。身份验证代码看起来像这样
public static LoginResult TryLogin(string loginName, string pwd)
{
string loginHash = BCrypt.Net.BCrypt.HashPassword(loginName, SHARED_SALT);
WidgetDataContext dc = new WidgetDataContext();
var record = (from rec in dc.usp_GetUserByLoginName(loginHash)
select rec).SingleOrDefault();
if (record == null)
return new LoginResult(null, "Invalid Login Name/Password");
if (record.FailedLoginCount >= MAX_CONSECUTIVE_LOGIN_FAILURES)
return new LoginResult(null, "You have exceeded your maximum number of Login failures. Your account is locked.");
if (record.Locked) // In case account is locked for another reason
return new LoginResult(null, "Your Account is locked.");
pwd = EncryptionServices.Encrypt(pwd, loginName);
pwd = BCrypt.Net.BCrypt.HashPassword(pwd, record.Salt);
if (pwd == record.Password)
{
record.FailedLoginCount = 0;
dc.SubmitChanges();
return new LoginResult(record.UserId, "Login Successful");
}
record.FailedLoginCount++;
dc.SubmitChanges();
return new LoginResult(null, "Invalid Login Name/Password");
}
如果管理员离开并接管数据库,则无法更改某些安全参数。退出的管理员将拥有用户名、密码和恢复方法。您指的是什么安全参数?SALT以及哈希登录名和密码将一直存储在数据库中。身份验证是什么样子的?'code'string loginHash=BCrypt.Net.BCrypt.HashPassword(loginName,SHARED_SALT);WidgetDataContext dc=新的WidgetDataContext();var record=(从dc.usp_GetUserByLoginName(loginHash)中的rec选择rec.SingleOrDefault();if(record==null)返回新的RequestResult(“无效的登录名/密码”);pwd=EncryptionServices.Encrypt(pwd,loginName);pwd=BCrypt.Net.BCrypt.HashPassword(pwd,record.Salt);如果(pwd==record.Password)'code'“实际上您正在将服务器端机密添加到存储的哈希中(您对密码进行哈希的过程)。”数据库1:Username用共享的salt和BCrypted腌制。密码使用AES加密,用户名作为加密密钥,然后使用唯一的随机salt和BCrypted进行加密。数据库2。用户名是纯文本。密码由唯一的salt和BCrypt组成。假设您知道这两个数据库是如何存储用户名/密码的,并且在这两种情况下都知道该过程的每个细节,那么使用第一个数据库恢复密码不是更困难吗?@antelopecarbuilding395-您获得的收益非常少。如果使用BCrypt作为哈希算法,攻击者必须使用暴力或尝试字典攻击。BCrypt将在每次猜测时使用大量时间来保护密码。您的第一步可以为每个用户执行一次(使用常量salt和username以及bcrypt),这样它们就不算了。在散列之前对密码进行加密需要一点时间,但您最好将其用于增加BCrypt的成本因素。使用用户名永远不会比使用随机salt和强独立密钥更好。“使用用户名永远不会比使用随机salt和强独立密钥更好”。“1.登录名通常是非常弱的密码。虽然人们正在学习密码必须是强密码,但登录名通常只包含一个带数字的名称,而且很短。“我在那里看到了我的问题。我会投入一半的计算时间来保护像Rover17这样的用户名,而不是像NkleJTG567F这样的密码!即使加强了对用户名的限制,哈希仍然会被共享的salt削弱。谢谢你们花时间回答我的问题。简单地说,我很快就把这个例子打出来了。它是一个模拟u