Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:这是BCrypt的好用法吗?_Java_Security_Passwords_Client Server_Bcrypt - Fatal编程技术网

Java:这是BCrypt的好用法吗?

Java:这是BCrypt的好用法吗?,java,security,passwords,client-server,bcrypt,Java,Security,Passwords,Client Server,Bcrypt,我想知道我当前的BCrypt实现是否正确,我知道我没有使用BCrypt.checkpw(),这可能会导致问题,因此这是我在这里验证它的主要原因 java容器类: abstract public class Hasher { public static String hash(final char[] input) { String output = Hasher.hash(new String(input)); for (int i = 0; i &

我想知道我当前的BCrypt实现是否正确,我知道我没有使用
BCrypt.checkpw()
,这可能会导致问题,因此这是我在这里验证它的主要原因

java容器类:

abstract public class Hasher {
    public static String hash(final char[] input) {   
        String output = Hasher.hash(new String(input));
        for (int i = 0; i < input.length; i++) {
            input[i] = 0;
        }
        return output;
    }

    public static String hash(final String input) {
        return BCrypt.hashpw(input, BCrypt.gensalt());
    }
}
所以散列是通过网络发送的,目前网络没有加密,但我计划添加它

创建帐户时的服务器实现:

public static Account createAccount(final String username, final String password) {
    String hashedPassword = Hasher.hash(password.toCharArray());
    return new Account(username, hashedPassword);
}
检查密码的服务器实现:

public boolean checkPassword(final String hashedPassword) {
    return this.hashedPassword.equals(hashedPassword);
}
this.hashedPassword
是服务器内存中的哈希值(启动时来自数据库)

我的设置的属性:

  • 登录会占用客户机大量时间,因为密码会散列在那里
  • 创建帐户/更改密码需要服务器花费大量时间,因为密码会在服务器上散列
  • 验证登录尝试几乎不需要服务器花费时间,因为不需要进行哈希运算
  • 如果有人获得了包含散列的数据库,那么破解每个帐户的密码将花费大量时间
  • 我仍然需要为
    BCrypt.gensalt()
    找出一个好的工作系数
请验证我的假设


注意。

此设置存在一些问题

1) salt应该是在散列过程中随机生成的值(在您的实现中似乎是这样)。由于客户端无法访问存储散列的数据库,因此客户端在创建登录散列时不知道要使用什么salt

2) 这个实现实际上并不是检查客户端传递的密码,而是检查客户端传递的密码散列。这意味着,如果有人获得了您的哈希数据库,他们可以立即使用这些哈希登录。然后不需要破解它们来提取密码,因为您不检查密码

这两个问题都可以通过移动所有哈希服务器端轻松解决

更新

关于你提到的问题

1) 如果您打算创建一个安全的系统,那么应该使用SSL/TLS。在clear中发送密码散列几乎和在clear中发送密码一样完全不安全。这两个想法都很糟糕。使用HTTPS


2) 执行服务器端哈希是一种非常普通的做法。哈希过程在计算上非常昂贵,足以使穷举搜索变得不切实际,但它不应妨碍您的身份验证工作流。如果你真的很担心被下药,请记录一个给定用户在过去N秒内尝试登录的次数。如果他们失败了一定次数,请锁定他们的帐户。

要验证提供的密码,您需要使用与存储密码相同的salt对其进行哈希。salt存储在“哈希”中(BCrypt哈希实际上不仅仅是哈希),这不包括验证部分吗?对身份验证客户端执行哈希通常是个坏主意。首先,如果有人真的偷走了你的哈希数据库,他们现在可以以任何人的身份登录,即使他们还没有破解任何密码。此外,由于盐是在散列过程中随机生成的,您的登录将永远不会生成两次相同的散列,因此将永远不会与服务器端的散列相匹配。@Aurand您能再详细说明一下吗?我看不到客户端和能够以任何人身份登录之间的直接联系。@skiwi否。客户端使用新生成的salt(
Hasher.hash(password)
)创建一个新的哈希,该哈希与服务器存储的哈希不相等。哈希服务器端的两个问题(我试图解决这个问题,但到目前为止失败了,不确定是否无法修复):1)我需要通过网络通道发送密码,2)这会给每次登录尝试的服务器带来很大压力,我当前的设置(如果有效)非常适合反击针对登录页面的DDoS攻击。下面是一个小问题:使用SSLSocketFactory是否是一个安全的通信通道?我应该瞄准什么样的散列时间(以秒为单位)?需要通过功系数随时间进行调整。是。关于散列时间,有各种各样的观点。从100毫秒到2秒,我都听到了。老实说,这个范围内的任何东西都是相当合理的。我倾向于认为~500毫秒是个好主意,但这是我个人的看法。在这个范围内的任何地方都会让散列破解非常痛苦。
public boolean checkPassword(final String hashedPassword) {
    return this.hashedPassword.equals(hashedPassword);
}