Строка Java в формате SHA1
Я пытаюсь сделать простой конвертер строк в SHA1 в Java, и это то, что у меня есть...
public static String toSHA1(byte[] convertme) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
}
catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new String(md.digest(convertme));
}
когда я передаю его toSHA1("password".getBytes()), Я получаю "[�a � ɹ??% % l�3~� �."Я знаю, что это, вероятно, простое исправление кодировки, такое как UTF-8, но может ли кто-нибудь сказать мне, что я должен сделать, чтобы получить то, что я хочу, что такое "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"? Или я делаю это совершенно неправильно?
Спасибо большое!
11 ответов:
обновление
Вы можете использовать Apache Commons Codec (версия 1.7+), чтобы сделать эту работу для вас.DigestUtils.sha1Hex(stringToConvertToSHexRepresentation)спасибо @Джон Онстотт за это предложение.
Ответ
Преобразуйте свой массив байтов в шестнадцатеричную строку. Real's How to tells you how.return byteArrayToHexString(md.digest(convertme))и (скопировано из Real's How To)
public static String byteArrayToHexString(byte[] b) { String result = ""; for (int i=0; i < b.length; i++) { result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 ); } return result; }
кстати, вы можете получить более компактный представление с использованием Base64. Apache Commons Codec API 1.4, это хорошая утилита, чтобы забрать всю боль. см. здесь
Это мое решение преобразования строки в sha1. Он хорошо работает в моем приложении для Android:
private static String encryptPassword(String password) { String sha1 = ""; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(password.getBytes("UTF-8")); sha1 = byteToHex(crypt.digest()); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } catch(UnsupportedEncodingException e) { e.printStackTrace(); } return sha1; } private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; }
С помощью класс хеширования гуавы:
Hashing.sha1().hashString( "password", Charsets.UTF_8 ).toString()
SHA-1 (и все другие алгоритмы хэширования) возвращают двоичные данные. Это означает, что (в Java) они производят
byte[]. Этоbyteмассив не представляют любые конкретные символы, что означает, что вы не можете просто превратить его вStringкак и ты.если вам понадобится
String, то вы должны отформатировать, чтоbyte[]таким образом, что можно представить какString(в противном случае, просто держитеbyte[]вокруг).два распространенных способа представления произвольного
byte[]в качестве печатаемых символов являются BASE64 или простые шестнадцатеричные строки (т. е. представляющие каждыйbyteдвумя шестнадцатеричными цифрами). Похоже, вы пытаетесь создать шестнадцатеричную строку.есть еще одна ловушка: если вы хотите получить SHA-1 Java
String, тогда вам нужно преобразовать этоStringдоbyte[]во-первых (как вход SHA-1 являетсяbyte[]Как хорошо). Если вы просто используетеmyString.getBytes()как вы показали, то он будет использовать платформу по умолчанию кодирование и как таковое будет зависеть от среды, в которой вы его запускаете (например, он может возвращать разные данные на основе языка/языкового стандарта вашей ОС).лучшее решение-указать кодировку для
Stringдоbyte[]преобразования такой:myString.getBytes("UTF-8"). Выбор UTF-8 (или другой кодировки, которая может представлять каждый символ Юникода) является самым безопасным выбором здесь.
просто используйте библиотеку кодеков Apache commons. У них есть служебный класс под названием DigestUtils
Не нужно вдаваться в подробности.
Это простое решение, которое может быть использовано при преобразовании строки в шестнадцатеричный формат:
private static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(password.getBytes("UTF-8")); return new BigInteger(1, crypt.digest()).toString(16); }
Как упоминалось ранее, используйте кодек apache commons. Это также рекомендуется весенними парнями (см. DigestUtils in Spring doc). Например:
DigestUtils.sha1Hex(b);определенно не будет использовать самый рейтинговый ответ здесь.
это не печать правильно, потому что вам нужно использовать кодировку Base64. С Java 8 вы можете кодировать с помощью Base64 класс шифратора.
public static String toSHA1(byte[] convertme) { md = MessageDigest.getInstance("SHA-1"); return Base64.getEncoder().encodeToString((md.digest(convertme)); }результат
это даст вам ожидаемый результат
5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
причина, по которой это не работает, заключается в том, что при вызове
String(md.digest(convertme)), вы говорите Java интерпретировать последовательность зашифрованных байтов как строку. То, что вы хотите, чтобы преобразовать байты в шестнадцатеричные символы.
преобразование массива байтов в шестнадцатеричную строку.
public static String toSHA1(byte[] convertme) { final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); MessageDigest md = null; try { md = MessageDigest.getInstance("SHA-1"); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] buf = md.digest(convertme); char[] chars = new char[2 * buf.length]; for (int i = 0; i < buf.length; ++i) { chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4]; chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F]; } return new String(chars); }
база 64 представление
SHA1хэш:String hashedVal = Base64.getEncoder().encodeToString(DigestUtils.sha1(stringValue.getBytes(Charset.forName("UTF-8"))));
Comments