经过一天的长时间编程后,我想发布一些对别人有用的东西。
几天前,我想知道如何使用正确的过程处理JPasswordField
的方法getPassword()
,以便将值传递给服务器并获得答案。
这就是问题:
如何以安全的方式从JPasswordField
正确获取值并处理它以创建服务器的登录过程?
答案 0 :(得分:4)
这是我达成的解决方案。
首先,我决定登录程序对我的目的来说足够安全,我不想向服务器发送一个普通密码而我不想存储一个普通密码(显然)在我的数据库中。
首先要说的是,保护密码的一个好方法是,它永远不会以简单易读的形式通过网络进行交换,这显然是因为中间有可能的"# 34;用少数几个词来说就是有人在去服务器的途中阅读你的消息。
密码需要进行哈希处理,这意味着它会转换为很长的十六进制字符序列。散列的好处是(希望)是单向的。您无法解密密码。
有很多算法要做,我选择SHA256。
然后对密码进行哈希处理,但就在我们之间,这可能还不够。如果一个黑客能够窃取哈希,那么有一些技巧可以让他成功地进行翻译"它的。只是为了在他的等式中添加一个变量,并使他的生活更加艰难,我们可以在哈希之前为密码添加一个盐。 salt是一段字符串,添加到我们想要密码的任何位置。这可以避免基于字典和最常用密码的某种攻击。
但如果一个比我训练得更好的黑客无法读取密码,我怎么能?
答案很简单,我不必这样做。
但要理解这一点,我们需要在注册程序中跳过一会儿"这是将新用户添加到我的数据库的时刻。就是这样:
所以登录程序将是这样的:
这应该很好,但在这种情况下,如果黑客知道共享密钥可以毫无问题地访问服务器,因为这样做我们只是更改了密码,不是可读的,但仍然可以直接使用。
为了避免这种行为,我们只需要在我们的链中添加一个段落:
现在程序很明确,我们有一个问题需要解决。如果我处理任何类型的String,它可以在内存中保留很长时间,所以如果我将我的密码放在String中,它可以在普通形式下长时间可读。这对我们来说不是那么好,但我们不是第一个考虑它的,java确实创建了一种避免此密码持久存在的方法。解决方案是使用一组字符。这是因为即使数组持久存储在内存中,其数据也会在内存中没有顺序传播,并且很难重新创建原始密码。
重新发明热水?是的,只需在JPasswordField中使用getPassword()方法。
但这对新手来说相当困难。我们得到一个char []数组,对于非专家来说很奇怪。
我们想到的第一件事就是将该数组转换为普通字符串....... 但这正是我想要避免的。所以我需要按原样处理数组。
我们需要一个方法来对密码进行salt和hash,结果可以是:
public static String digestSalted(String salt, char[] password) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
ArrayList<Byte> list = new ArrayList<Byte>();
for (int i = 0; i < password.length; i++) {
//String ch = String.valueOf(password[i]);
//byte[] b = ch.getBytes();
//for (int j = 0; j < b.length; j++) {
// list.add(b[j]);
//}
list.add((byte)password[i]);
}
byte[] saltInBytes = salt.getBytes();
byte[] toBeHashed = new byte[(saltInBytes.length + list.size())];
for (int i = 0; i < saltInBytes.length; i++) {
toBeHashed[i] = saltInBytes[i];
}
for (int i = saltInBytes.length; i < list.size() + saltInBytes.length; i++) {
toBeHashed[i] = list.get(i - saltInBytes.length);
}
md.update(toBeHashed);
byte byteData[] = md.digest();
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
String hex = Integer.toHexString(0xff & byteData[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
此方法创建一个通过许多小字符串的字节数组,然后附加salt。盐渍后,它会使用SHA256对结果进行哈希处理。
现在返回可以是一个字符串,因为经过哈希处理并且没有安全问题。
这为问题的第一部分提供了解决方案。
第二部分是在服务器和客户端之间实现我们的协议。
我只会在客户端显示足以理解该过程的代码。 我正在使用阻塞队列,从套接字读取消息时放置。这是代码:
public void login(String nickname, char[] password) {
if (cl == null) {
throw new RuntimeException();
}
long s = Sys.getTime();
cl.send("NICK " + nickname);
IncomingMessage reply = null;
try {
reply = this.mh.getMessage(); //The response to NICK msg
if (reply.getCommand().equalsIgnoreCase("LOGIN")) {
ArrayList<String> params = reply.getParams();
String accountSalt = params.get(0);
String randomSalt = params.get(1);
try {
String sharedSecret = SHAHash.digestSalted(accountSalt, password);
String saltedSharedSecret = SHAHash.digestSalted(randomSalt, sharedSecret);
if (saltedSharedSecret != null) {
cl.send("PASS " + saltedSharedSecret);
reply = this.mh.getMessage();
if (reply.getCommand().equalsIgnoreCase("WELCOME") && reply.getParams().get(0).equals(nickname)) {
// ************ LOG ************ //
LOG.config("Logged in.");
// ***************************** //
this.running = true;
this.loggedIn = true;
mh.startExecutor();
LOG.config("Time passed: " + (Sys.getTime() - s));
mh.startGame();
} else {
// ************ LOG ************ //
LOG.warning("A problem has occured while trying to login to the server.");
// ***************************** //
JOptionPane.showMessageDialog(null, "Error while logging to the server, shutting down.\n- ERROR 006 -");
System.exit(0);
}
}
} catch (NoSuchAlgorithmException e) {
// ************ LOG ************ //
LOG.warning("Error while SHA hashing the password, shutting down.");
// ***************************** //
JOptionPane.showMessageDialog(null, "Error while SHA hashing the password, shutting down.\n- ERROR 005 -");
System.exit(0);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
代码,现在我们已经清楚协议如何工作,很容易理解应该考虑的事情是this.mh.getMessage()
是一种阻塞方法,这意味着线程会等到在尝试获取之前,队列中有一些东西可供使用。
这(几乎)我如何解决我的问题。如果答案中有任何错误或者您需要澄清,请告诉我。 我希望这对某人有用。有一个很好的编程