SecretKeyFactory.getInstance(PBKDF2WithHmacSHA512) выдает NoSuchAlgorithmException

После небольшого исследования и некоторой работы я, наконец, смог хешировать пароль, теперь у меня есть вопрос, который у меня на уме. Я использовал метод SHA1, и я хотел бы попробовать использовать SHA512, потому что мне сказали, что это лучше (более безопасный), поэтому мой код немного разбросан по всему месту, но я думаю, что он понятен:

public class Safety
{
   //calling some parameters for possible later changes
   public static final String algorithm = "PBKDF2WithHmacSHA1";
   public static final int saltbytesize = 24;
   public static final int hashbytesize = 24;
   public static final int iterations = 1000;
   public static final int iIndex = 0;
   public static final int sIndex = 1;
   public static final int pbkIndex = 2;

   public static Users passwordHash(Users user) throws NoSuchAlgorithmException,
                                                       InvalidKeySpecException
   {
      SecureRandom sR = new SecureRandom();

      byte[] pws = new byte[saltbytesize];

      sR.nextBytes(pws);
      byte[] pwh = pbkdf2(user.getPassword().toCharArray(), pws, iterations, hashbytesize);

      user.setPassword(toHex(pwh));

      byte[] sas = new byte[saltbytesize];

      sR.nextBytes(sas);

      byte[] sah = pbkdf2(user.getsA().toCharArray(), sas, iterations, hashbytesize);

      user.setsA(toHex(sah));

      user.setUserhash(pws);

      user.setSahash(sas);

      return user;
   }

   public static boolean hashpassword(String username, String password, Users user)
   throws NoSuchAlgorithmException,
          InvalidKeySpecException
   {
      byte[] pws = user.getUserhash();

      byte[] pwh = pbkdf2(password.toCharArray(), pws, iterations, hashbytesize);

      String searcher = toHex(pwh) + username;

      String searched = user.getPassword() + user.getUsername();

      if (searcher.equals(searched))
      {
         return true;
      }
      return false;
   }

   private static byte[] pbkdf2(char[] password, byte[] salt,
                                int iterations, int bytes)
      throws NoSuchAlgorithmException, InvalidKeySpecException
   {
      PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8);
      SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
      return skf.generateSecret(spec).getEncoded();
   }

   private static String toHex(byte[] array)
   {
      BigInteger bi = new BigInteger(1, array);

      String hex = bi.toString(16);

      int paddingLength = (array.length * 2) - hex.length();

      if (paddingLength > 0)
         return String.format("%0" + paddingLength + "d", 0) + hex;
      else
         return hex;
   }
}

Итак, это мой код, однако я не смог сделать этот SHA512, и я уже пробовал public static final String algorithm = "PBKDF2WithHmacSHA512", но это не кажется правильной строкой для алгоритма, поскольку он выдает исключение такого алгоритма.

Я также приветствую любые изменения, которые сделают код лучше.

как указано выше! соответствующие несколько строк кода

общедоступный статический финальный строковый алгоритм = "PBKDF2WithHmacSHA512"‹‹‹‹‹


person Fahadalkadhi95    schedule 27.12.2013    source источник
comment
всегда форматируйте свой код, чтобы он выглядел красиво, если вы просите людей посмотреть на него. Ясность кода — половина вопроса.   -  person Mike 'Pomax' Kamermans    schedule 28.12.2013
comment
Спасибо, и я это знаю, но то, как я хакаю, ограничивает мою способность сделать так, чтобы это выглядело красиво.   -  person Fahadalkadhi95    schedule 28.12.2013
comment
не совсем. код, который вы вставили, имеет смещенные интервалы и сжатые операторы и т. д., по крайней мере, исправьте это, чтобы быть приятным для потенциальных ответов на вопросы =)   -  person Mike 'Pomax' Kamermans    schedule 28.12.2013
comment
Починил это. Основная проблема с форматированием вашего кода, по-видимому, заключалась в табуляциях — в коде никогда не должно быть табуляции, а при редактировании и выводе могут использоваться разные позиции табуляции, поэтому отступы могут выглядеть по-разному. Кроме того, если вы используете приличную IDE (скажем, NetBeans), на самом деле довольно сложно писать код без приличного форматирования.   -  person Bernhard Barker    schedule 28.12.2013
comment
TY @Dukeling, ты мой герой :)   -  person Fahadalkadhi95    schedule 28.12.2013
comment
Можете ли вы сократить свой пример до нескольких соответствующих строк кода?   -  person Bill    schedule 28.12.2013


Ответы (1)


Это невозможно из коробки

Реализация OpenJDK предоставляет только PBKDF2HmacSHA1Factory.java с закодированным дайджестом "HmacSHA1". Насколько я тестировал, Oracle JDK в этом смысле ничем не отличается.

Что вам нужно сделать, так это получить PBKDF2HmacSHA1Factory (да ладно, он открыт!) и добавить параметр в его конструктор. Вы можете избежать путаницы при создании собственного Provider и просто инициализировать и использовать свой factory следующим образом:

PBKDF_SecretKeyFactory kf = new PBKDF_SecretKeyFactory("HmacSHA512");
KeySpec ks = new PBEKeySpec(password,salt,iterations,bitlen);
byte key[] = kf.engineGenerateSecret(ks).getEncoded();
person Javier    schedule 27.12.2013
comment
Нужно ли мне сохранять ключ [] в базе данных? - person Fahadalkadhi95; 28.12.2013
comment
Да. Несмотря на название, результирующий ключ на самом деле является выходом PBKDF. Злоумышленник не может (кроме грубой силы) получить исходный пароль из ключа. - person Javier; 28.12.2013
comment
еще одна вещь, которую я должен был спросить заранее, когда кто-то входит в систему, что я делаю, это извлекаю ключ и соль и снова хеширую его? точнее, для чего нужен ключ? или это на самом деле хешированный пароль, и я слишком туп, чтобы понять? - person Fahadalkadhi95; 28.12.2013
comment
Ключ представляет собой хешированный пароль. Когда кто-то входит в систему, вы снова хешируете предоставленный пароль (с той же солью, алгоритмом и количеством итераций) и проверяете, совпадают ли хэши. Преимущество заключается в том, что пароль никогда не сохраняется в вашей базе данных. - person Javier; 28.12.2013
comment
TY очень, то это то, что я искал :) - person Fahadalkadhi95; 28.12.2013
comment
я попробовал, и он говорит, что PBKDF_SecretKeyFactory не может быть разрешен как тип? - person Fahadalkadhi95; 28.12.2013
comment
Этот класс не существует. Вам придется написать это. См. источник PBKDF2HmacSHA1Factory, указанный выше. - person Javier; 29.12.2013
comment
гм, я понял это, но извините за мое ..... знание .... как мне написать именно ссылку, которую вы мне дали, на класс с именем «PBKDF2HmacSHA1Factory»? - person Fahadalkadhi95; 29.12.2013
comment
Я думаю, что изменения тривиальны: вам нужна фабрика для PBKDF с HmacSHA512, класс PBKDF2HmacSHA1Factory — это фабрика для PBKDF с HmacSHA1: скопируйте исходный код, переименуйте его, замените HmacSHA1 на HmacSHA512 и счастливого нового года. - person Javier; 29.12.2013
comment
Вас тоже с Новым годом, и пусть ваш следующий год будет таким, каким вы хотите, я попробую и дам вам обратную связь, надеюсь, это сработает, и я начинаю работать над своим следующим шагом :) - person Fahadalkadhi95; 29.12.2013
comment
я думаю, мне также нужно обновить свой JDK, потому что есть класс, который не установлен в этом классе, я попробую установить эти классы и немного поэкспериментировать - person Fahadalkadhi95; 29.12.2013
comment
В Java 8 теперь доступен PBKDF2HmacSHA512 — docs.oracle.com /javase/8/docs/technotes/guides/security/ - person Anti-weakpasswords; 08.02.2016