2013-11-26 2 views
0

Я пытаюсь реализовать хэширование паролей SHA1 с расширением ключа в сочетании с UUID в качестве соли. Соль хранится как столбец в моей учетной записи пользователя внутри бэкэнда базы данных, поэтому каждый пользователь будет генерировать свою собственную уникальную соль.Регенерация SHA-1 хеша не соответствует сохраненной хэш-базе данных

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

registerUser извлекает объект пользователя из createUser, а затем сохраняется в базе данных. Затем я использую validatePassword для регенерации хэша. Ниже приведены полные фрагменты кода. Это моя первая попытка защитить пароли, я, очевидно, что-то схожу с ума, но я не могу обнаружить ошибку.

public void registerUser() { 
    try { 

     Usertable newUser = createUser(); 

     // user constructed at this point, persist it to the database. 
     utx.begin(); 
     em.persist(newUser); 
     utx.commit(); 

     // Register user with Meter 
     Meter myMeter = (Meter) em.createNamedQuery("Meter.findByMeterid").setParameter("meterid", this.meterId).getSingleResult(); 
     myMeter.setUsername(newUser); 

     utx.begin(); 
     em.merge(myMeter); 
     utx.commit(); 

    } catch (NoSuchAlgorithmException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (NotSupportedException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (SystemException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (RollbackException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (HeuristicMixedException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (HeuristicRollbackException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (SecurityException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (IllegalStateException ex) { 
     Logger.getLogger(RegisterBean.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

private Usertable createUser() throws NoSuchAlgorithmException { 
    Security securityLevel = (Security) em.createNamedQuery("Security.findBySecurityid").setParameter("securityid", SECURITY_LEVEL_USER).getSingleResult(); 
    Usertable newUser = new Usertable(); 

    // generate UUID to be used as a salt. 
    UUID salt = UUID.randomUUID(); 

    // generate hash 
    MessageDigest msgDigest = MessageDigest.getInstance("SHA-1"); 
    String inputText = new String(salt.toString() + this.password); 
    for (int i = 0; i < ITERATIONS; i++) { 
     msgDigest.update(inputText.getBytes()); 
     byte rawByte[] = msgDigest.digest(); 
     inputText = (new BASE64Encoder()).encode(rawByte); 
    } 

    String hashValue = inputText; 

    newUser.setUsername(this.userName); 
    newUser.setSecurityid(securityLevel); 
    newUser.setSalt(salt.toString()); 
    newUser.setPassword(hashValue); 

    return newUser; 
} 

public void validatePassword(FacesContext context, UIComponent ui, Object passwordField) { 
    try { 
     UIInput userNameInput = (UIInput) context.getViewRoot().findComponent("regform:userName"); 
     String userName = (String) userNameInput.getValue(); 

     Usertable myUser = (Usertable) em.createNamedQuery("Usertable.findByUsername").setParameter("username", userName).getSingleResult(); 

     // generate hash 
     MessageDigest msgDigest = MessageDigest.getInstance("SHA-1"); 
     String inputText = new String(myUser.getSalt() + this.password); 
     for (int i = 0; i < ITERATIONS; i++) { 
      msgDigest.update(inputText.getBytes()); 
      byte rawByte[] = msgDigest.digest(); 
      inputText = (new BASE64Encoder()).encode(rawByte); 
     } 

     if (!inputText.equals(myUser.getPassword())) { 
      String message = "Username or password incorrect"; 
      throw new ValidatorException(new FacesMessage(message)); 
     } else { 
      // password is valid, store user into session and mark logged in. 
      this.myUser = myUser; 
     } 

    } catch (NoSuchAlgorithmException ex) { 
     Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (NoResultException ex) { 
     String message = "Username or password incorrect"; 
     throw new ValidatorException(new FacesMessage(message)); 
    } 

} 
+0

Я не думаю, что то, что я пишу здесь, является решением. Мне просто интересно, не должен ли ваш цикл содержать msgDigest.reset() перед msgDigest.update()? Я думаю, вы хотите начать новый расчет SHA-1 для каждого цикла ... ОК забудьте об этом; дайджест (...) должен быть уже сброшен ... (не знал этого) –

+0

Замечание: вы знаете, что SHA-1 является [устаревшим] (http://blogs.technet.com/b/pki/archive /2013/11/12/sha1-deprecation-policy.aspx), правильно? – ajb

+1

Да Я знаю, что SHA-1 устаревает и удаляется, это часть задания для академических целей, и SHA-1 был одним из моих предложений от факультета не из-за его силы, а благодаря тому, что он реализован в широком спектре языки. – Nebri

ответ

1

Вы уверены, что this.password правильно установлен до validatePassword() называется? Вы проверили начальное значение inputText как в createUser(), так и в validatePassword(), чтобы убедиться, что они соответствуют?

Этот метод хеширования паролей небезопасен. Из-за коллизий в выходе хеш-функции, чем больше итераций вы выполняете, тем меньше энтропии будет содержать полученный хеш. Чтобы сохранить тот же уровень непредсказуемости, который найден в исходном пароле, вам необходимо добавить пароль для каждого раунда хэширования.

Лучший способ сделать это - использовать существующую библиотеку хэширования паролей, такую ​​как scrypt или bcrypt, или, по крайней мере, функцию деривации ключей, такую ​​как PBKDF2, которая встроена в большинство Java-приложений.

+0

Я уверен, что this.password установлен правильно. Я перебираю свой отладчик последние пару часов, проверяя все переменные и входы. – Nebri

+0

@Nebri Ну, хеширование само по себе не проблема. Я предполагаю, что проблема заключается в том, что ваш механизм сохранения не смог сохранить или получить правильную информацию. Другие вещи, которые нужно проверить, могут быть различными деталями кодирования base-64 (у Apache есть несколько кодеров, которые содержат пробелы по-разному) или запускают методы генерации и проверки хэша в разных процессах, которые используют разные кодировки символов. – erickson

+0

Я говорю, что хэширование не является проблемой, потому что я избавился от материала настойчивости и сам выполнил ваш код хэширования/проверки. Это было непросто, из-за того, как вы смешивали все вместе, но модульный тест правильно подтвердил меня. – erickson

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

  • Нет связанных вопросов^_^