我有一个简单的Android客户端需要与简单的C#HTTP侦听器“对话”。我想通过在POST请求中传递用户名/密码来提供基本级别的身份验证。
MD5哈希在C#中是微不足道的,并且为我的需求提供了足够的安全性,但我似乎无法在android端找到如何做到这一点。
编辑:只是为了解决有关MD5弱点的问题 - C#服务器在我的Android客户端用户的PC上运行。在许多情况下,他们将使用自己的局域网上的Wi-Fi访问服务器,但他们可能会自己冒险从互联网上访问它。此外,服务器上的服务需要使用MD5的传递到我无法控制的第三方应用程序。答案 0 :(得分:208)
Here是您可以使用的实现(已更新以使用更新的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 is considered broken and can be easily exploited)的系统,但有时基本任务就足够了。
答案 1 :(得分:42)
在Android 2.2中,接受的答案对我不起作用。我不知道为什么,但它正在“吃掉”我的一些零(0)。 Apache commons 也无法在Android 2.2上运行,因为它使用仅从Android 2.3.x开始支持的方法。另外,如果你想只是MD5一个字符串,那么Apache公共文件太复杂了。为什么要让整个库只使用一个小函数...
最后,我发现以下代码片段here对我来说非常合适。我希望它对某人有用......
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;
}
答案 2 :(得分:26)
androidsnippets.com代码无法可靠地运行,因为0似乎会从生成的哈希中删除。
更好的实施是here。
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; }
答案 3 :(得分:17)
如果使用Apache Commons Codec是一个选项,那么这将是一个更短的实现:
String md5Hex = new String(Hex.encodeHex(DigestUtils.md5(data)));
或SHA:
String shaHex= new String(Hex.encodeHex(DigestUtils.sha("textToHash")));
Source以上。
请点击链接并提出他的解决方案,以奖励正确的人。
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>
答案 4 :(得分:11)
上面使用DigestUtils的解决方案对我不起作用。在我的Apache commons版本(2013年的最新版本)中没有这样的类。
我找到了另一个解决方案here in one blog。它完美无缺,不需要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;
答案 5 :(得分:9)
这是Andranik和Den Delimarsky在上面的答案的略微变化,但它更简洁,不需要任何按位逻辑。相反,它使用内置的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;
}
}
答案 6 :(得分:3)
我在Kotlin做了一个简单的图书馆。
在Root build.gradle
添加allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
在App build.gradle
implementation 'com.github.1AboveAll:Hasher:-SNAPSHOT'
用法
在Kotlin
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。
有关图书馆的更多信息
答案 7 :(得分:1)
在我们的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应用程序中相同(然后帮助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();
}
答案 8 :(得分:0)
MD5有点旧,SHA-1是更好的算法,there is a example here。
(同样正如他们在该帖子中所述,Java自己处理此问题,没有Android特定代码。)
答案 9 :(得分:0)
我使用下面的方法通过传递你想要获得md5的字符串给我md5
$scope.comment = $scope.comment || {
user_id: 'amcpanaligan',
comment_text: 'sample'
//// other object property declaration goes here...
};
答案 10 :(得分:0)
真的,在其他建议中,过于浪费于Hex()转换。
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);
}
答案 11 :(得分:0)
请使用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;
}
答案 12 :(得分:0)
这里是@Andranik回答的Kotlin版本。
我们需要将getBytes
更改为toByteArray
(不需要添加字符集UTF-8,因为toByteArray
的默认字符集为UTF-8),并将array [i]转换为integer < / p>
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
}
希望有帮助
答案 13 :(得分:0)
这对我来说是完美的,我用它来获取LIST Array上的MD5(然后将其转换为JSON对象),但是如果您只需要将其应用于数据上。键入format,将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;
}
答案 14 :(得分:0)
有用的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) }
}
答案 15 :(得分:-1)
为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
}