密码哈希每次都以不同方式生成

时间:2014-12-30 17:44:31

标签: java hash jetty

我正致力于密码保护我正在构建的码头服务器。我使用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。

关于发生了什么的任何想法?这真的很奇怪。

3 个答案:

答案 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));

生成一致的诊断输出。