MD5加密

java中实现MD5加密通常有两种方法

方法一:通过java自带的java.security.MessageDigest实现加密

package com.wantao.md5;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class MessageDigestTest {
	private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d","e", "f" };
	
	/**
	 * 将1个字节(1 byte = 8 bit)转为 2个十六进制位 1个16进制位 = 4个二进制位 (即4 bit)
	 * 转换思路:最简单的办法就是先将byte转为10进制的int类型,然后将十进制数转十六进制
	 */
	private static String byteToHexString(byte b) {
		// byte类型赋值给int变量时,java会自动将byte类型转int类型,从低位类型到高位类型自动转换
		int n = b;
		// 将十进制数转十六进制
		if (n < 0)
			n += 256;
		int d1 = n / 16;
		int d2 = n % 16;
		// d1和d2通过访问数组变量的方式转成16进制字符串;比如 d1 为12 ,那么就转为"c";
		// 因为int类型不会有a,b,c,d,e,f等表示16进制的字符
		return hexDigits[d1] + hexDigits[d2];
	}

	/**
	 * 将字节数组里每个字节转成2个16进制位的字符串后拼接起来
	 */
	private static String byteArrayToHexString(byte b[]) {
		StringBuffer resultSb = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			resultSb.append(byteToHexString(b[i]));
		}
		return resultSb.toString();
	}

	/**
	 * MD5算法 默认固定长度是 128bit 即 32个16进制位 String origin :需要进行MD5计算的字符串 String
	 * charsetname :MD5算法的编码
	 */
	private static String MD5_32(String origin, String charsetname) {
		String resultString = null;
		try {
			// 1,创建MessageDigest对象
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 2,向MessageDigest传送要计算的数据;传入的数据需要转化为指定编码的字节数组
			md.update(origin.getBytes(charsetname));
			// 3,计算摘要
			byte[] bytesResult = md.digest();

			// 第2步和第3步可以合并成下面一步
			// byte[] bytesResult = md.digest(origin.getBytes(charsetname));

			// 4,将字节数组转换为16进制位
			resultString = byteArrayToHexString(bytesResult);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resultString;

	}

	public static void main(String[] args) {
		String origin = "selenium";
		// 默认MD5计算得到128 bit的摘要,即32个 16进制位
		String result_32 = MD5_32(origin, "utf-8");
		System.out.println(result_32); // E807F1FCF82D132F9BB018CA6738A19F
	}
}


 
 

注意:

MessageDigestdigest()返回的是byte[],而我们期望的到的MD5加密后的值应该是32位的16进制数,所以还要将byte[]转换为16进制数组成的字符串.
②如果你看过别人的代码,有的人直接调用的MessageDigestdigest(byte[] input)而没有调用update(向MessageDigest传送要计算的数据;传入的数据需要转化为指定编码的字节数组)方法,那是因为digest()已经将update()封装了,所以不要感到奇怪.
有图有真相

方法二:通过DigestUtils工具类(需要导入commons-codec)

package com.wantao.md5;
import org.apache.commons.codec.digest.DigestUtils;
public class DigestUtilsTest {
	public static String md5(String str) {
		String result = DigestUtils.md5Hex(str);
		return result;
	}
	public static void main(String[] args) {
		String result = md5("selenium");
		System.out.println(result);
	}
}

可以发现使用DigestUtils返回的直接就是32位的16进制数组成的字符串,使用它就简单多了(推荐使用).

应用:使用两次MD5对用户密码进行加密

MD5对用户密码进行加密,大家就懂,可为什么要两次呢?
在这里插入图片描述
第一次MD5+固定Salt加密:
           第一次MD5是在浏览器端,通过js文件中进行MD5加密,由于http报文的明文传输,如果传输的数据被截获(例如使用fiddler等抓包工具),那用户密码将暴露无疑,所以我们使用MD5和固定Salt将表单的关键数据(例如密码)进行加密.
第二次MD5+随机Salt加密:
           第二次MD5是在服务器端完成的,它将用户的关键信息进行加密后存入到数据库中,这样如果数据库的被盗后也得不到用户原始的密码信息.

注意:

MD5加密是不可逆的,但是你可能会发现有一些md5在线解密的网站能够通过密文获得你原始的数据,但它并不是反推出来的,而是通过反向查询,穷举字符组合的方式,创建了明文密文对应查询数据库,这样获得的你的原始数据.(例如它查询出123456的MD5加密后的密文为abcdef,然后将这一对数据存入数据库,当你查询输入密文为abcdef的时候,它就返回了123456的原文)

我们接下来就来实现一下完整两次MD5加密的应用

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/blueimp-md5/2.6.0/js/md5.js"></script>
<script type="text/javascript">
$(function(){
	function formEncryption(password){//md5加密
		var salt="sakura";
		var str=salt.charAt(5)+salt.charAt(2)+password+salt.charAt(0);//使用固定的salt
		return md5(str);
	}
	$("#aaa").click(function(){
		$.ajax({
			url:"doLogin",
			type:"post",
			data:{
				"password":formEncryption($(".password").val)
			},
			success:function(){		
			}
		});
	});
});
</script>
</head>
<body>
<form>
password:<input name="password" type="password"/>
<button id="aaa">提交</button>
</form>
</body>
</html>

 
 

第一步:我们提交含有密码的表单,将表单的密码值在js中通过使用md5.js来进行md5加密.
第二步:在数据验证时调用MD5Utill进行MD5加密

MD5Util.java

package com.wantao.md5;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;
@Component
public class MD5Util {	
    //MD5加密
	public static String md5(String password) {
		return DigestUtils.md5Hex(password);
	}	
	//明文密码和固定salt生成MD5,用于用户传输到服务器的时候加密,使得传输的密码不是明文密码
	private static final String salt="sakura";
	public static String formEncryption(String password) {
		String str=salt.charAt(5)+salt.charAt(2)+password+salt.charAt(0);
		return md5(str);
	}	
	//第一次MD5的密码和随机salt生成的MD5,用于存储到数据库密码的加密
	public static String dbEncryption(String password,String salt) {
		String str=salt.charAt(0)+salt.charAt(2)+password+salt.charAt(5);
		return md5(str);
	}	
}

 
 

MD5TestController.java

package com.wantao.controller;
import java.util.UUID;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import com.wantao.md5.MD5Util;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
public class MD5TestController {
	@PostMapping("/doLogin")
	public void doLogin(String password) {
		log.info("用户传输过来的密码:"+password);
		String salt=UUID.randomUUID().toString().substring(1, 10);
		String dbPassword=MD5Util.dbEncryption(password, salt);
		log.info("存入数据库的密码:"+dbPassword);
	}
}

 
 

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Selenium399

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值