Mam prostego klienta Android, który musi „rozmawiać” z prostym odbiornikiem HTTP C #. Chcę zapewnić podstawowy poziom uwierzytelniania, przekazując nazwę użytkownika / hasło w żądaniach POST.
Haszowanie MD5 jest trywialne w C # i zapewnia wystarczające zabezpieczenia dla moich potrzeb, ale nie mogę znaleźć sposobu na zrobienie tego na końcu Androida.
EDYCJA: Aby rozwiązać obawy związane ze słabością MD5 - serwer C # działa na komputerach użytkowników mojego klienta Android. W wielu przypadkach będą uzyskiwać dostęp do serwera za pomocą Wi-Fi we własnych sieciach LAN, ale na własne ryzyko mogą uzyskać do niego dostęp przez Internet. Również usługa na serwerze musi korzystać z przejścia MD5 do aplikacji innej firmy, nad którą nie mam kontroli.
android
cryptography
md5
Squonk
źródło
źródło
Odpowiedzi:
Oto implementacja, której możesz użyć (zaktualizowana, aby używać bardziej aktualnych konwencji Java - zamiast
for:each
pętli ):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 ""; }
Chociaż nie jest to zalecane dla systemów, które wymagają nawet podstawowego poziomu bezpieczeństwa (MD5 jest uważane za zepsute i można je łatwo wykorzystać ), czasami wystarcza do podstawowych zadań.
źródło
NoSuchAlgorithmException
)?Zaakceptowana odpowiedź nie działa dla mnie w systemie Android 2.2. Nie wiem dlaczego, ale to „zjadało” moje zera (0). Apache commons również nie działało na Androidzie 2.2, ponieważ używa metod, które są obsługiwane tylko od Androida 2.3.x. Ponadto, jeśli chcesz tylko MD5 jako ciąg, Apache commons jest na to zbyt skomplikowane. Dlaczego należy zachować całą bibliotekę, aby używać z niej tylko małej funkcji ...
Wreszcie znalazłem tutaj następujący fragment kodu , który działał idealnie dla mnie. Mam nadzieję, że komuś się przyda ...
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; }
źródło
Kod androidsnippets.com nie działa niezawodnie, ponieważ wydaje się, że z wynikowego skrótu zostały wycięte cyfry zerowe.
Lepsze wdrożenie jest tutaj .
źródło
Jeśli użycie kodeka Apache Commons jest opcją, byłaby to krótsza implementacja:
String md5Hex = new String(Hex.encodeHex(DigestUtils.md5(data)));
Lub SHA:
String shaHex= new String(Hex.encodeHex(DigestUtils.sha("textToHash")));
Źródło powyżej.
Kliknij link i zagłosuj na jego rozwiązanie, aby nagrodzić właściwą osobę.
Link do repozytorium Maven: https://mvnrepository.com/artifact/commons-codec/commons-codec
Obecna zależność Maven (stan na 6 lipca 2016 r.):
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency>
źródło
Powyższe rozwiązanie przy użyciu DigestUtils nie działa dla mnie. W mojej wersji Apache commons (najnowsza na 2013 rok) nie ma takiej klasy.
Znalazłem tutaj inne rozwiązanie na jednym blogu . Działa idealnie i nie potrzebuje wspólnych zasobów Apache. Wygląda na trochę krótszą niż kod w zaakceptowanej odpowiedzi powyżej.
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; } }
Będziesz potrzebować tych importów:
import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;
źródło
Jest to niewielka odmiana odpowiedzi Andranika i Dena Delimarskiego powyżej, ale jest nieco bardziej zwięzła i nie wymaga żadnej logiki bitowej. Zamiast tego używa wbudowanej
String.format
metody do konwersji bajtów na dwuznakowe ciągi szesnastkowe (nie usuwa zer). Zwykle tylko skomentowałbym ich odpowiedzi, ale nie mam reputacji, aby to zrobić.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; } }
Jeśli zamiast tego chcesz zwrócić ciąg z małych liter, po prostu zmień
%02X
na%02x
.Edycja: używając BigInteger, podobnie jak w przypadku odpowiedzi wzbozon, możesz uczynić odpowiedź jeszcze bardziej zwięzłą:
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; } }
źródło
Zrobiłem prostą bibliotekę w Kotlinie.
Dodaj w katalogu głównym build.gradle
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
w aplikacji build.gradle
implementation 'com.github.1AboveAll:Hasher:-SNAPSHOT'
Stosowanie
W Kotlinie
val ob = Hasher()
Następnie użyj metody hash ()
ob.hash("String_You_Want_To_Encode",Hasher.MD5) ob.hash("String_You_Want_To_Encode",Hasher.SHA_1)
Zwróci odpowiednio MD5 i SHA-1.
Więcej o Bibliotece
https://github.com/ihimanshurawat/Hasher
źródło
Oto wersja Kotlina z odpowiedzi @Andranik. Musimy zmienić
getBytes
natoByteArray
(nie musimy dodawać zestawu znaków UTF-8, ponieważ domyślnytoByteArray
zestaw znaków to UTF-8) i rzutować tablicę [i] na liczbę całkowitą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 }
Mam nadzieję, że to pomoże
źródło
W naszej aplikacji MVC generujemy dla 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; }
i to samo w aplikacji na Androida (wtedyk pomaga Andranikowi)
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(); }
źródło
Użyłem poniższej metody, aby dać mi md5, przekazując ciąg, dla którego chcesz uzyskać 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 ""; }
źródło
Użyj SHA-512, MD5 jest niezabezpieczone
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; }
źródło
MD5 jest trochę stary, SHA-1 to lepszy algorytm, tutaj jest przykład .
( Również, jak zauważają w tym poście, Java obsługuje to samodzielnie, bez kodu specyficznego dla Androida ).
źródło
Tak naprawdę w innych sugestiach przeważa zbyt marnotrawna konwersja metody 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); }
źródło
to działa idealnie dla mnie, użyłem tego, aby uzyskać MD5 na LIST Array (następnie przekonwertować go na obiekt JSON), ale jeśli potrzebujesz go tylko zastosować do swoich danych. wpisz format, zamień JsonObject na swój.
Zwłaszcza jeśli masz niezgodność z implementacją Pythona MD5, użyj tego!
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; }
źródło
Przydatny przykład funkcji rozszerzenia 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) } }
źródło
Dostarczone rozwiązania dla języka Scala (trochę krótsze):
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 }
źródło