MD5 хеширование в Android

У меня есть простой клиент для Android, который должен «разговаривать» с простым слушателем HTTP C #. Я хочу обеспечить базовый уровень аутентификации, передав имя пользователя / пароль в POST-запросах.

Хеширование MD5 тривиально в C # и обеспечивает достаточную безопасность для моих нужд, но я не могу найти, как это сделать на стороне Android.

EDIT: просто для решения проблем, вызванных слабостью MD5 – сервер C # работает на ПК пользователей моего Android-клиента. Во многих случаях они будут обращаться к серверу с помощью Wi-Fi в своих локальных сетях, но на свой страх и риск они могут получить доступ к нему из Интернета. Также служба на сервере должна использовать сквозной проход для MD5 для стороннего приложения, в котором я не контролирую.

Вот реализация, которую вы можете использовать (обновленная для использования более современных соглашений Java – for:each цикла, StringBuilder вместо StringBuffer ):

 public static final 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 считается сломанным и его можно легко использовать ), для базовых задач иногда бывает достаточно.

Принятый ответ не работал для меня в Android 2.2. Я не знаю, почему, но это было «есть» некоторые из моих нhive (0). Apache также не работал на Android 2.2, потому что он использует методы, которые поддерживаются только с Android 2.3.x. Кроме того, если вы хотите, чтобы всего лишь MD5-строка, для нее слишком сложным для Apache. Почему нужно хранить всю библиотеку, чтобы использовать из нее только небольшую функцию …

Наконец, я нашел следующий fragment кода, который отлично работал для меня. Надеюсь, это будет полезно для кого-то …

 public String MD5(String md5) { try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); byte[] array = md.digest(md5.getBytes()); 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) { } return null; } 

Код androidsnippets.com не работает надежно, потому что 0 получается из результирующего hashа.

Лучшая реализация здесь .

 public static String MD5_Hash(String s) { MessageDigest m = null; try { m = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } m.update(s.getBytes(),0,s.length()); String hash = new BigInteger(1, m.digest()).toString(16); return hash; } 

Если использование Apache Commons Codec является вариантом, то это будет более короткая реализация:

 String md5Hex = new String(Hex.encodeHex(DigestUtils.md5(data))); 

Или SHA:

 String shaHex= new String(Hex.encodeHex(DigestUtils.sha("textToHash"))); 

Источник выше.

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


Ссылка Maven repo: https://mvnrepository.com/artifact/commons-codec/commons-codec

Текущая зависимость Maven (по состоянию на 6 июля 2016 года):

   commons-codec commons-codec 1.10  

Решение выше, использующее DigestUtils, не работало для меня. В моей версии Apache commons (последняя на 2013 год) такого classа нет.

Я нашел другое решение здесь в одном блоге . Он отлично работает и не нуждается в долях 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 для преобразования байтов в два символа шестнадцатеричных строк (не 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; } } 

MD5 немного стар, SHA-1 – лучший алгоритм, здесь есть пример .

( Также, как они отмечают в этой статье, Java обрабатывает это самостоятельно, не имеет специального кода для Android ).

В нашем MVC-приложении мы генерируем для long param

 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 (thenk помогает Andranik)

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

Я создал простую библиотеку в Котлине.

Добавить в Root build.gradle

 allprojects { repositories { ... maven { url 'https://jitpack.io' } } } 

в приложении build.gradle

 implementation 'com.github.1AboveAll:Hasher:-SNAPSHOT' 

Применение

В Котлине

 val ob = Hasher() 

Затем используйте метод hash ()

 ob.hash("String_You_Want_To_Encode",ob.MD5) ob.hash("String_You_Want_To_Encode",ob.SHA_1) 

Он будет возвращать MD5 и SHA-1 соответственно.

Подробнее о библиотеке

https://github.com/1AboveAll/Hasher

Я использовал ниже метод, чтобы дать мне 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 ""; } 

На самом деле слишком расточительное преобразование 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); } 

Представленные решения для языка 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 } 
  • Размер подписи RSA?
  • Атрибуты AES-NI включены по умолчанию?
  • Как расшифровать шифрованную строку SHA-256?
  • Шифровать пароль в файлах конфигурации?
  • iText / BouncyCastle ClassNotFound org.bouncycastle.asn1.DEREncodable и org.bouncycastle.tsp.TimeStampTokenInfo
  • Можно ли расшифровывать hashи md5?
  • Как долго переборщить соленый hash SHA-512? (соль предоставляется)
  • как использовать RSA для шифрования файлов (огромные данные) в C #
  • Что делает оператор?
  • Какой тип данных использовать для hashированного поля пароля и какой длины?
  • Как я могу подписать файл с помощью RSA и SHA256 с .NET?
  • Давайте будем гением компьютера.