我正致力于密码保护我正在构建的码头服务器。我使用Java的MessageDigest类来散列密码。我创建了这个测试类,它工作得很好:
String hash = "<hashOfMyPassword";
String pass = "<myPassword>";
byte[] data = pass.getBytes();
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
md.update(data);
MessageDigest passMD = null;
try {
passMD = (MessageDigest) md.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] passHash = passMD.digest();
System.out.println(passHash.toString().equals(hash));
但当我把它移到我的码头服务器时,它开始表现得很奇怪。这是方法:
public void handle(String s, Request req, HttpServletRequest hreq,
HttpServletResponse hres) throws IOException, ServletException {
hres.setContentType("text/plain");
hres.setStatus(HttpServletResponse.SC_OK);
req.setHandled(true);
if (!running) {
//Validate password
String pass = hreq.getParameter("password");
hres.getWriter().println(pass);
byte[] data = pass.getBytes();
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
md.update(data);
MessageDigest passMD = null;
try {
passMD = (MessageDigest) md.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] passHash = passMD.digest();
hres.getWriter().println(passHash.toString());
if (passHash.toString().equals(hash)) {
//dostuff
} else {
hres.getWriter().println("invalid password");
}
}
}
}
(在任何人说出某些话之前,我知道我很奇怪地传递密码,但这个项目没问题)
这与以前完全相同,但这次我总是得到不同的哈希值,密码永远不会匹配。我两次通过相同的密码,第一次得到像#34; [B @ 33ab7e65&#34;接下来我得到&#34; [B @ 58eb5b4&#34;。
我使用curl来访问服务器btw。
关于发生了什么的任何想法?这真的很奇怪。
答案 0 :(得分:4)
您将passHash
(字节数组)转换为toString
的字符串。这实际上并没有完全获取数组的内容 - Java在数组上toString
的实现是无用的,它只是打印出数组位置的一部分地址在记忆中。
不要使用字符串相等比较哈希,直接比较它!输入hash
作为字节数组,并使用Arrays.equals()
进行比较。
Arrays.equals(passHash, hash)
答案 1 :(得分:0)
您的代码的问题在于您在哈希上调用toString()而根本不使用哈希。您无法通过调用toString()将字节数组转换为字符串。
passHash.toString().equals(hash)
答案 2 :(得分:0)
Commons Lang 3&#39; ArrayUtils包含一种生成数组字符串版本的可靠方法。
@Test
public void arrayToString(){
int[] a = {1,2,3};
int[] b = Arrays.copyOf(a, 3);
String aRawToString = a.toString();
String bRawToString = b.toString();
String aCommonsLangToString = ArrayUtils.toString(a);
String bCommonsLangToString = ArrayUtils.toString(b);
Assert.assertNotEquals(aRawToString, bRawToString);
Assert.assertEquals(aCommonsLangToString, bCommonsLangToString);
System.out.println(aRawToString);
System.out.println(bRawToString);
System.out.println(aCommonsLangToString);
System.out.println(bCommonsLangToString);
}
下面的输出演示了使用toString(为相同的数组生成不同答案)和解决方案的问题。
[I@504814f9
[I@2c59109c
{1,2,3}
{1,2,3}
来自原始问题的这行代码:
hres.getWriter().println(passHash.toString());
可以改写为
hres.getWriter().println(ArrayUtils.toString(passHash));
生成一致的诊断输出。