Android中的MD5散列
我有一个简单的Android客户端需要“谈”到一个简单的C#HTTP侦听器。 我想通过在POST请求中传递用户名/密码来提供基本的身份validation级别。
在C#中MD5哈希是微不足道的,并提供足够的安全性,我的需求,但我似乎无法find如何做到这一点在Android端。
编辑:只是为了解决有关MD5的弱点提出的担忧 – C#服务器运行在我的Android客户端的用户的个人电脑上。 在很多情况下,他们将在自己的局域网上使用Wi-Fi访问服务器,但是他们可能select通过互联网访问它们,但风险自负。 此外,服务器上的服务需要使用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 ""; }
尽pipe不build议系统涉及到基本的安全级别(MD5 被认为是破坏的并且可以被轻易利用 ),但有时候这对基本任务来说还是足够的。
在Android 2.2中接受的答案并不适用于我。 我不知道为什么,但它“吃”了我的一些零(0)。 Apache公用程序也没有在Android 2.2上工作,因为它使用的方法只支持从Android 2.3.x开始。 另外,如果你想只是一个stringMD5,Apache的公共太复杂了。 为什么要让整个图书馆只使用一个小function呢?
最后,我在这里find了下面的代码片断,这对我来说非常合适。 我希望这对某个人有用
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看起来被切掉了散列结果。
这里有一个更好的实现。
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")));
上面的来源 。
请按照链接和upvote他的解决scheme奖励正确的人。
Maven回购链接: https : //mvnrepository.com/artifact/commons-codec/commons-codec
当前Maven依赖(截至2016年7月6日):
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency>
上面使用DigestUtils的解决scheme不适合我。 在我的Apache版本(2013年的最新版本)中,没有这样的类。
我在一个博客中find了另一个解决scheme。 它工作完美,并不需要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;
这是Andranik和Den Delimarsky上面的答案的一个细微的变化,但它更简洁一点,不需要任何按位逻辑。 相反,它使用内置的String.format
方法将字节转换为两个字符的hexstring(不去掉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; } }
如果您想要返回小写string, %02X
%02x
更改为%02x
。
编辑:像使用wzbozon的答案一样使用BigInteger,可以使答案更加简洁:
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-1algorithm比较好, 这里有一个例子 。
( 就像他们在那篇文章中提到的那样,Java自己处理,而不是Android特定的代码。 )
在我们的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应用程序一样(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(); }
我已经使用下面的方法给我md5通过传递你想要得到md5的string
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 ""; }
对于其他build议来说,对于()()转换太浪费了。
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语言提供的解决scheme(稍短一点):
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 }