问题描述
我想知道如果我当前的BCrypt的实现是正确的,我知道,我不使用 BCrypt.checkpw()这可能会导致一个问题,这是我在此验证的主要原因。
Hasher.java容器类:
code> abstract public class Hasher {
public static String hash(final char [] input){
String output = Hasher.hash(new String(input));
for(int i = 0; i input [i] = 0;
}
return output;
}
public static String hash(final String input){
return BCrypt.hashpw(input,BCrypt.gensalt());
}
}
这里有一个问题: JPasswordField 为了安全起见给了一个 char [] ,但 BCrypt.hashpw()接受字符串。如何避免String在我的内存中浮动?
登录的客户端实现:
String hashedPassword = Hasher.hash(password);
Network.getInstance()。send(login+ username ++ hashedPassword);
所以哈希值通过网络发送,目前网络没有加密, 。
创建帐户时的服务器实现:
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
我的设置的属性:
$ b(在启动时来自数据库)
请验证我的假设。
回答。
此设置有一些问题。
1)salt应该是在哈希过程中随机生成的值(因为它似乎在你的实现中。由于客户端无法访问存储散列的数据库,因此客户端在创建登录散列时不知道要使用什么盐。
2)此实现不是实际上检查客户端传递的密码,它检查客户端传递的密码哈希值。这意味着,如果有人获取您的哈希数据库,他们可以立即使用这些哈希值登录。然后不需要破解他们提取密码,因为你不检查密码。
这些问题都可以很容易地解决通过移动所有散列服务器端。 p>
更新
关于您提及的问题。
1)如果您有创建安全系统的任何意图,您应该使用SSL / TLS。发送密码哈希在明确几乎是完全不安全发送密码在明确。这两个都是一个可怕的想法。使用HTTPS。
2)执行服务器端哈希是一个很普通的做法。散列过程在计算上是昂贵的,使得穷举搜索不切实际,但它不应该妨碍您的认证工作流。如果你真的很关心DoSed,记住一个给定用户在过去N秒内尝试登录的次数。如果他们失败了一定次数,请锁定他们的帐户。
I would like to know if my current implementation of BCrypt is correct, I am aware that I am not using BCrypt.checkpw() which may lead to an issue so that is the main reason I verify it here.
Hasher.java container class:
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()); } }
One concern here: JPasswordField gives me a char[] for security reasons, however BCrypt.hashpw() only accepts Strings. How can I avoid that String from floating around in my memory?
The client implementation of logging in:
String hashedPassword = Hasher.hash(password); Network.getInstance().send("login " + username + " " + hashedPassword);
So the hash gets sent over the network, currently the network is not encrypted but I plan on adding that.
The server implementation on account creation:
public static Account createAccount(final String username, final String password) { String hashedPassword = Hasher.hash(password.toCharArray()); return new Account(username, hashedPassword); }
The server implementation of checking password:
public boolean checkPassword(final String hashedPassword) { return this.hashedPassword.equals(hashedPassword); }
With this.hashedPassword being the hash that is in the server's memory (which comes from a database on bootup).
Properties of my setup:
- Logging in takes the client significant time, as the password is hashed there.
- Creating an account/Changing password takes the server significant time, as the password is hashed on the server then.
- Validating login attempts takes the server practically no time, as no hashing needs to be done.
- If someone gets hold of the database containing the hashes, then it will take him significant time to crack the password per account.
- I still need to figure out a good work factor for the BCrypt.gensalt().
Please verify my assumptions.
Regards.
There are a couple problems with this setup.
1) The salt should be a value randomly generated during the hashing process (as it seems to be in your implementation. Since the client does not have access to the database of stored hashes, the client will not know what salt to use when creating a login hash.
2) This implementation is not actually checking the password passed by the client, it's checking the password hash passed by the client. That means that if someone gets your database of hashes, they can immediately use those hashes to login. Then do not need to crack them to extract passwords, since you do not check the passwords.
Both these issues can be easily solved by moving all hashing server side.
Update
Regarding the issues you mentioned.
1) If you have any intention of creating a secure system, you should be using SSL/TLS. Sending password hashes in the clear is almost as totally insecure as sending passwords in the clear. Both are a terrible idea. Use HTTPS.
2) Performing server side hashing is a pretty ordinary practice. The hashing process is computationally expensive enough to make exhaustive search impractical, but it shouldn't hinder your authentication workflow. If you're really concerned about being DoSed, keep track of how many times a given user has tried to login in the last N seconds. If they've failed a certain number of times, lock their account.
这篇关于Java:这是BCrypt的好用法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!