У меня есть простой клиент Android, которому нужно «разговаривать» с простым слушателем HTTP C #. Я хочу обеспечить базовый уровень аутентификации, передав имя пользователя / пароль в запросах POST.
Хеширование MD5 тривиально в C # и обеспечивает достаточную безопасность для моих нужд, но я не могу найти, как это сделать на стороне Android.
РЕДАКТИРОВАТЬ: Просто чтобы устранить озабоченность по поводу слабости MD5 - сервер C # работает на ПК пользователей моего клиента Android. Во многих случаях они будут получать доступ к серверу с помощью Wi-Fi в своих собственных локальных сетях, но на свой страх и риск они могут выбрать доступ к нему из Интернета. Также служба на сервере должна использовать сквозную передачу MD5 для стороннего приложения, которое я не контролирую.
источник
Ответы:
Вот реализация, которую вы можете использовать (обновленная для использования более современных соглашений Java -
for:each
циклStringBuilder
вместоStringBuffer
):public static String md5(final String s) { final String MD5 = "MD5"; try { // Create MD5 Hash MessageDigest digest = java.security.MessageDigest .getInstance(MD5); digest.update(s.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuilder hexString = new StringBuilder(); for (byte aMessageDigest : messageDigest) { String h = Integer.toHexString(0xFF & aMessageDigest); while (h.length() < 2) h = "0" + h; hexString.append(h); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; }
Хотя это не рекомендуется для систем, которые включают даже базовый уровень безопасности (MD5 считается сломанным и может быть легко взломан ), иногда его достаточно для основных задач.
источник
NoSuchAlgorithmException
)?Принятый ответ не сработал для меня в Android 2.2. Не знаю почему, но он «ел» некоторые из моих нулей (0). Apache Commons также не работал на Android 2.2, потому что он использует методы, которые поддерживаются только начиная с Android 2.3.x. Кроме того, если вы хотите использовать только строку MD5, Apache commons слишком сложен для этого. Почему нужно хранить целую библиотеку, чтобы использовать только небольшую функцию из нее ...
Наконец -то я нашел следующий фрагмент кода здесь , который работал отлично для меня. Надеюсь, кому-то будет полезно ...
public String MD5(String md5) { try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); byte[] array = md.digest(md5.getBytes("UTF-8")); StringBuffer sb = new StringBuffer(); for (int i = 0; i < array.length; ++i) { sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3)); } return sb.toString(); } catch (java.security.NoSuchAlgorithmException e) { } catch(UnsupportedEncodingException ex){ } return null; }
источник
Код androidsnippets.com не работает надежно, потому что 0 кажется вырезанным из полученного хэша.
Лучшая реализация здесь .
источник
Если возможно использование кодека Apache Commons, это будет более короткая реализация:
String md5Hex = new String(Hex.encodeHex(DigestUtils.md5(data)));
Или SHA:
String shaHex= new String(Hex.encodeHex(DigestUtils.sha("textToHash")));
Источник для выше.
Пожалуйста, перейдите по ссылке и проголосуйте за его решение, чтобы наградить правильного человека.
Ссылка на репозиторий Maven: https://mvnrepository.com/artifact/commons-codec/commons-codec
Текущая зависимость Maven (по состоянию на 6 июля 2016 г.):
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency>
источник
Приведенное выше решение с использованием DigestUtils у меня не сработало. В моей версии Apache commons (последней на 2013 год) такого класса нет.
Я нашел другое решение здесь, в одном блоге . Он отлично работает и не требует общих ресурсов Apache. Он выглядит немного короче, чем код в принятом ответе выше.
public static String getMd5Hash(String input) { try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] messageDigest = md.digest(input.getBytes()); BigInteger number = new BigInteger(1, messageDigest); String md5 = number.toString(16); while (md5.length() < 32) md5 = "0" + md5; return md5; } catch (NoSuchAlgorithmException e) { Log.e("MD5", e.getLocalizedMessage()); return null; } }
Вам понадобится этот импорт:
import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;
источник
Это небольшая вариация ответов Андраника и Дена Делимарского выше, но она немного более краткая и не требует какой-либо побитовой логики. Вместо этого он использует встроенный
String.format
метод для преобразования байтов в двухсимвольные шестнадцатеричные строки (не удаляет 0). Обычно я просто комментирую их ответы, но у меня нет репутации для этого.public static String md5(String input) { try { MessageDigest md = MessageDigest.getInstance("MD5"); StringBuilder hexString = new StringBuilder(); for (byte digestByte : md.digest(input.getBytes())) hexString.append(String.format("%02X", digestByte)); return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } }
Если вы хотите вместо этого вернуть строку в нижнем регистре, просто измените ее
%02X
на%02x
.Изменить: используя BigInteger, как с ответом wzbozon, вы можете сделать ответ еще более кратким:
public static String md5(String input) { try { MessageDigest md = MessageDigest.getInstance("MD5"); BigInteger md5Data = new BigInteger(1, md.digest(input.getBytes())); return String.Format("%032X", md5Data); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } }
источник
Я сделал простую библиотеку в Котлине.
Добавьте в корень build.gradle
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
в App build.gradle
implementation 'com.github.1AboveAll:Hasher:-SNAPSHOT'
Применение
В Котлине
val ob = Hasher()
Затем используйте метод hash ()
ob.hash("String_You_Want_To_Encode",Hasher.MD5) ob.hash("String_You_Want_To_Encode",Hasher.SHA_1)
Он вернет MD5 и SHA-1 соответственно.
Подробнее о библиотеке
https://github.com/ihimanshurawat/Hasher
источник
Вот версия Котлина из ответа @Andranik. Нам нужно изменить
getBytes
наtoByteArray
(не нужно добавлять кодировку UTF-8, потому что кодировка по умолчаниюtoByteArray
- UTF-8) и преобразовать array [i] в целое числоfun String.md5(): String? { try { val md = MessageDigest.getInstance("MD5") val array = md.digest(this.toByteArray()) val sb = StringBuffer() for (i in array.indices) { sb.append(Integer.toHexString(array[i].toInt() and 0xFF or 0x100).substring(1, 3)) } return sb.toString() } catch (e: java.security.NoSuchAlgorithmException) { } catch (ex: UnsupportedEncodingException) { } return null }
Надеюсь, это поможет
источник
В нашем приложении MVC мы генерируем длинный параметр
using System.Security.Cryptography; using System.Text; ... public static string getMD5(long id) { // convert string result = (id ^ long.MaxValue).ToString("X") + "-ANY-TEXT"; using (MD5 md5Hash = MD5.Create()) { // Convert the input string to a byte array and compute the hash. byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(result)); // Create a new Stringbuilder to collect the bytes and create a string. StringBuilder sBuilder = new StringBuilder(); for (int i = 0; i < data.Length; i++) sBuilder.Append(data[i].ToString("x2")); // Return the hexadecimal string. result = sBuilder.ToString().ToUpper(); } return result; }
и то же самое в приложении для Android (затемк помогает Андранику)
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; ... public String getIdHash(long id){ String hash = null; long intId = id ^ Long.MAX_VALUE; String md5 = String.format("%X-ANY-TEXT", intId); try { MessageDigest md = java.security.MessageDigest.getInstance("MD5"); byte[] arr = md.digest(md5.getBytes()); StringBuffer sb = new StringBuffer(); for (int i = 0; i < arr.length; ++i) sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1,3)); hash = sb.toString(); } catch (NoSuchAlgorithmException e) { Log.e("MD5", e.getMessage()); } return hash.toUpperCase(); }
источник
Я использовал метод ниже, чтобы дать мне md5, передав строку, для которой вы хотите получить md5
public static String getMd5Key(String password) { // String password = "12131123984335"; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(password.getBytes()); byte byteData[] = md.digest(); //convert the byte to hex format method 1 StringBuffer sb = new StringBuffer(); for (int i = 0; i < byteData.length; i++) { sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)); } System.out.println("Digest(in hex format):: " + sb.toString()); //convert the byte to hex format method 2 StringBuffer hexString = new StringBuffer(); for (int i = 0; i < byteData.length; i++) { String hex = Integer.toHexString(0xff & byteData[i]); if (hex.length() == 1) hexString.append('0'); hexString.append(hex); } System.out.println("Digest(in hex format):: " + hexString.toString()); return hexString.toString(); } catch (Exception e) { // TODO: handle exception } return ""; }
источник
Используйте SHA-512, MD5 небезопасен
public static String getSHA512SecurePassword(String passwordToHash) { String generatedPassword = null; try { MessageDigest md = MessageDigest.getInstance("SHA-512"); md.update("everybreathyoutake".getBytes()); byte[] bytes = md.digest(passwordToHash.getBytes()); StringBuilder sb = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); } generatedPassword = sb.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return generatedPassword; }
источник
MD5 немного устарел, SHA-1 - лучший алгоритм, здесь есть пример .
( Также, как они отмечают в этом сообщении, Java справляется с этим самостоятельно, без специального кода для Android. )
источник
На самом деле, в других предложениях преобладает слишком расточительное преобразование toHex ().
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); public static String md5string(String s) { return toHex(md5plain(s)); } public static byte[] md5plain(String s) { final String MD5 = "MD5"; try { // Create MD5 Hash MessageDigest digest = java.security.MessageDigest.getInstance(MD5); digest.update(s.getBytes()); return digest.digest(); } catch (NoSuchAlgorithmException e) { // never happens e.printStackTrace(); return null; } } public static String toHex(byte[] buf) { char[] hexChars = new char[buf.length * 2]; int v; for (int i = 0; i < buf.length; i++) { v = buf[i] & 0xFF; hexChars[i * 2] = HEX_ARRAY[v >>> 4]; hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F]; } return new String(hexChars); }
источник
это отлично работает для меня, я использовал это, чтобы получить MD5 в массиве LIST (затем преобразовать его в объект JSON), но если вам нужно применить его только к своим данным. введите формат, замените JsonObject на свой.
Особенно, если у вас есть несоответствие с реализацией Python MD5, используйте это!
private static String md5(List<AccelerationSensor> sensor) { Gson gson= new Gson(); byte[] JsonObject = new byte[0]; try { JsonObject = gson.toJson(sensor).getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } MessageDigest m = null; try { m = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] thedigest = m.digest(JsonObject); String hash = String.format("%032x", new BigInteger(1, thedigest)); return hash; }
источник
Пример полезной функции расширения Kotlin
fun String.toMD5(): String { val bytes = MessageDigest.getInstance("MD5").digest(this.toByteArray()) return bytes.toHex() } fun ByteArray.toHex(): String { return joinToString("") { "%02x".format(it) } }
источник
Предоставленные решения для языка Scala (немного короче):
def getMd5(content: Array[Byte]) = try { val md = MessageDigest.getInstance("MD5") val bytes = md.digest(content) bytes.map(b => Integer.toHexString((b + 0x100) % 0x100)).mkString } catch { case ex: Throwable => null }
источник