MD5加密、加盐

在计算机安全领域,md5是使用比较广泛的一种散列函数,用来保护信息传输的完整性。那么,md5有什么作用呢?下面本文针对md5是什么,以及md5的作用做个简单的介绍。

md5是什么?

md5是一种信息摘要算法,一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值,用来确保信息传输完整一致性。

MD5加密算法是不可逆的。

MD5算法是单向散列算法的一种。单向散列算法也称为HASH算法,是一种将任意长度的信息压缩至某一固定长度(称之为消息摘要)的函数(该压缩过程不可逆)。在MD5算法中,这个摘要是指将任意数据映射成一个128位长的摘要信息。并且其是不可逆的,即从摘要信息无法反向推演中原文。MD5算法最终生成的是一个128位长的数据,从原理上说,有2^128种可能,这是一个非常巨大的数据,约等于3.4乘10的38次方,虽然这个是个天文数字,但是世界上可以进行加密的数据原则上说是无限的,因此是可能存在不同的内容经过MD5加密后得到同样的摘要信息,但这个碰中的概率非常小。

注意:md5值不是唯一的,也就是一个原始数据,只对应一个md5值,但是一个md5值,可能对应多个原始数据。且md5值是可以被破解的,例撞库破解。

撞库破解

关于撞库,这是概率比较低的解密方法,原理是:通过建立大型的数据库,把日常的各种句子通过md5加密成为密文,不断积累更新大量句子,放在庞大的数据库里;然后,有人拿了别人的密文,想查询真实的密码,就需要把密文拿到这个数据库的网站(免费MD5加密解密:md5在线加密解密)去查询。

md5有什么作用?

作用一:数字签名

MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,我将这段话“md5是什么,md5的这些用途你都知道吗”写在一个叫 read.txt文件中,并对这个read.txt产生一个MD5的值(密文:7a1189ca1650ef630a6c2b0206f42d8b)并记录在案,然后我可以传播这个文件给别人,别人如果修改了文件中的任何内容,那么我对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。

作用二:一致性验证

MD5的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。比如,在Unix下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如:

MD5 (tanajiya.tar.gz) = 38b8c2c1093dd0fec383a9d9ac940515

MD5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的MD5信息摘要。

作用三:安全访问认证

MD5还广泛用于操作系统的登录认证上,如Unix、各类BSD系统登录密码、数字签名等诸多方面。如在Unix系统中用户的密码是以MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这可以避免用户的密码被具有系统管理员权限的用户知道。

但经过哈希函数加密后的密码也不是绝对的安全,这时候就需要为密码加盐

(Salt) 是什么?

就是一个随机生成的字符串。我们将盐与原始密码连接/拼接(concat)在一起(放在前面或后面都可以),然后将concat后的字符串加密。Salt这个值是由系统随机生成的,并且只有系统知道。即便两个用户使用了同一个密码,由于系统为它们生成的salt值不同,散列值也是不同的。

我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如MD5密码破解网站),得到某用户的密码。

加Salt可以一定程度上解决这一问题。所谓加Salt方法,就是加点“佐料”(Salt这个单词就是盐的意思)。其基本想法是这样的:当用户首次提供密码时(通常是注册时),由系统自动往这个密码里撒一些“佐料”,然后再散列。而当用户登录时,系统为用户提供的代码撒上同样的“佐料”,然后散列,再比较散列值,已确定密码是否正确。

这样也就变成了将密码+自定义的盐值来取MD5。但是如果黑客拿到了你的固定的盐值,那这样也不安全了。所以比较好的做法是用随机盐值。用户登陆时再根据用户名取到这个随机的盐值来计算MD5。

MD5加盐

一般使用的加盐

即将用户名和密码字符串相加再MD5,这样的MD5摘要基本上不可反查。但有时候用户名可能会发生变化,发生变化后密码即不可用了(验证密码实际上就是再次计算摘要的过程)。

因此我们做了一个非常简单的加盐算法,每次保存密码到数据库时,都生成一个随机16位数字,将这16位数字和密码相加再求MD5摘要,然后在摘要中再将这16位数字按规则掺入形成一个48位的字符串。

在验证密码时再从48位字符串中按规则提取16位数字,和用户输入的密码相加再MD5。按照这种方法形成的结果肯定是不可直接反查的,且同一个密码每次保存时形成的摘要也都是不同的。

Demo

package com.cjian.security;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.SecureRandom;

/**
 * @Author: cjian
 * @Date: 2022/10/31 16:53
 * @Des:
 */
public class MD5Demo {
    public static void main(String[] args) {
        SecureRandom secureRandom = new SecureRandom();
        byte[] randomBytes = new byte[16];
        secureRandom.nextBytes(randomBytes);

        //生成的randomBytes可以通过对称加密存储起来
        String originalValue = new String(randomBytes) + "cjian";
        System.out.println("MD5加密后的字符串:" + setPassword(originalValue));
    }

    public static String setPassword(String str) {
        try {
            System.out.println("要加密的字符串:" + str);
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/cj_eryue/article/details/127619696
今日推荐