MD5加密浅析

MD5加密的概念

MD5加密是一种常用的信息摘要算法,主要用于保证数据的一致性以及签名验证,他是一种不可逆的加密算法。

MD5加密是将任意的字节数组加密成32个字节的数据,然后他们在形式上表现为32位的16进制数。

MD5加密的简单使用

我们来看下MD5加密在Java上的简单应用。

Java已经帮我们实现好了MD5加密,我们只需要调用系统函数就可以实现了。调用顺序按如下步骤:

第一步

获取MD5加密的对象:

try {
    messagedigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsaex) {
    System.err.println(MD5Util.class.getName() + "初始化失败,MessageDigest不支持MD5Util。");
    nsaex.printStackTrace();
}
第二步

传入要加密的数据:

byte[] secretBytes = messagedigest.digest(str.getBytes());

加密的数据也可以分次传入:

InputStream fis;
fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
int numRead = 0;
while ((numRead = fis.read(buffer)) > 0) {
    messagedigest.update(buffer, 0, numRead);
}
fis.close();
byte[] secretBytes = messagedigest.digest();

返回的byte数组是长度为16的数组。

第三步

将加密得到的byte数组转换为我们通常见到的MD5加密后的样子:

protected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};


private static String bufferToHex(byte bytes[], int m, int n) {
    StringBuffer stringbuffer = new StringBuffer(2 * n);
    int k = m + n;
    for (int l = m; l < k; l++) {
        appendHexPair(bytes[l], stringbuffer);
    }
    return stringbuffer.toString();
}

private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
    char c0 = hexDigits[(bt & 0xf0) >>> 4];// 取字节中高 4 位的数字转换
    char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换
    stringbuffer.append(c0);
    stringbuffer.append(c1);
}

如此就得到了加密后的字符串。

注意我们通常见到的将byte转换为加密后的字符串还有一种写法,就是使用BigInteger这个类:

String md5code = new BigInteger(1, secretBytes).toString(16);

但是这种写法有一个问题,就是如果加密后字符串最高位数0,就会被省略:

String str = new BigInteger(1, new byte[]{0, 16}).toString(16);
System.out.println(str);
//输出10

所以使用BigInteger正确做法如下:

String md5code = new BigInteger(1, secretBytes).toString(16);
for (int i = 0; i < 32 - md5code.length(); i++) {
    md5code = "0" + md5code;
}

以上就是MD5在Java上的简单实现。

MD5加密的实用场景

我们来看下MD5加密的应用场景。

由于MD5是不可逆的,所以对于一些加密后传输,然后在另一端解密的场景都不适用,它主要运用于对信息的隐藏以及保障数据的一致性等。

下面我们举几个具体的使用MD5加密的场景。

用户密码

用户的密码是非常敏感的数据,它传输或者存储的时候,如果直接使用明文会造成安全隐患。

例如明文存在客户端本地,客户端被root破解后就能够直接拿到文件从而找到密码,存在服务器数据库里面的密码也有被破解服务器后拿到密码的风险,而且能够被后台管理人员看到密码,而在传输过程中,如果发生DNS劫持,也能够被拿到密码。

所以密码如果进行传输和存储最好是使用MD5加密后,客户端和服务端比对加密字符串,如果一致密码校验就通过。

接口签名

网络接口如果不做限制,任意一方都能够调用到接口并且实现一些业务,会带来很大的安全隐患,为了避免这种情况,可以选择在接口添加一个签名参数。

例如,对于网络接口https://wanandroid.com/wxarticle/chapters/json ,如果再添加一个签名参数sign,他的值取“be happy”+全路径MD5签名后的字符串,然后后台在收到请求后,对签名进行验证,就能够很好的防止第三方恶意调用。

文件一致性校验

文件在传输过程中的损坏等情况时有发生,在保证文件一致的时候可以使用MD5校验。

例如,在客户端下载大文件的时候,一般会做断点续存的机制,那么就要这样的一个场景:文件下载了一部分后,被终止了下载,然后在此期间服务器的文件更新了,客户端在此下载的时候,下载的文件就是有问题的了,这样如果不做校验就会发生错误,而如果服务端在下发文件的时候,还下发一个MD5值,客户端在下载完成后检验下载完的文件的MD5与服务端下发的MD5值,不一致就删掉文件重新下载,就能够避免这种情况。

MD5加密的安全与破解

以加密密码为例,由于MD5加密是不可逆的,且加密字符串之间的相似度与原始字符串无关,不能通过加密字符串的相识度比对来修正原始字符串,所以对于MD5的破解一般是基于暴力破解,而MD5加密的结果共有16的32次方种,想要暴力破解这么大数据量现在的计算机还做不到,所以常规意义下MD5的安全性是很高的。

那么现在市面上盛行的MD5密码的破解是如何做的呢?这是由于大部分人设置的密码都是相对简单的,一般为纯数字或者英文加数字等,这样在暴力破解的时候,不要按部就班的去尝试,直接用常用的密码加密后去比对,就能够减少很多的计算量,从而达到破解的目的。

为了对抗这种情况,保护用户的密码信息,可以在用户的密码上加上一些通用的前后缀,例如用户设置密码为 123456,这种如果被拿到加密后的字符串,很容易被撞库破解,但是我们手动给其加上前后缀,使用 abc123456xyz ,这样被破解的概率就会低很多。

发布了19 篇原创文章 · 获赞 8 · 访问量 4041

猜你喜欢

转载自blog.csdn.net/u014068277/article/details/103115288