2014-12-30 2 views
1

Я работаю над паролем, защищающим причал, который я строю. Я использую Java MessageDigest класс для хеширования паролей. Я создал этот тестовый класс и это прекрасно работает:Пароль hash генерируется по-разному каждый раз

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"); 
      } 
     } 
    } 
} 

(прежде чем кто-то говорит, я знаю, я передаю пароль причудливо, но это нормально для этого проекта)

Это точно так же это, как и раньше, но на этот раз я всегда получаются разные хэши, и пароли никогда не совпадают. Я пропускаю один и тот же пароль дважды, и в первый раз я получаю что-то вроде «[B @ 33ab7e65», а следующий я получаю «[B @ 58eb5b4».

Я использую завиток для доступа к серверу.

Любые идеи о том, что происходит? Это действительно странно.

+0

В верхней части класса. это частный статический хеш String. Я создал его перед рукой. –

+0

Защита паролей через простое хеширование ** неэффективна **, я рекомендую вам перейти на алгоритм типа «PBKDF # 2», «Bcrypt» или «Scrypt». Сама Java содержит поддержку «PBKDF # 2», а остальные могут быть получены через общедоступные публичные библиотеки (например, Bouncy Castle). – initramfs

ответ

4

Вы преобразования passHash, массив байтов, в строку с toString. На самом деле это совсем не связано с содержимым вашего массива - реализация Java toString на массивах довольно бесполезна и просто распечатывает часть адреса расположения массива в памяти.

Не сравнивайте хэш с использованием равенства строк, сравните его напрямую! Введите hash как массив байтов, а также используйте Arrays.equals(), чтобы сравнить их.

Arrays.equals(passHash, hash) 
0

Проблема с вашим кодом заключается в том, что вы вызываете toString() в хэше и не используете хэш вообще. Вы не можете преобразовать массив байтов в строку, вызвав toString().

passHash.toString().equals(hash) 
0

Commons Lang 3-х 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 (который генерирует разные ответы для одинаковых массивов) и раствор.

[[email protected] 
[[email protected] 
{1,2,3} 
{1,2,3} 

Эта строка кода от первоначального вопроса:

hres.getWriter().println(passHash.toString()); 

можно переписать в виде

hres.getWriter().println(ArrayUtils.toString(passHash)); 

генерировать последовательный диагностический выход.

Смежные вопросы