java/web工具类之MD5、AES、Base64算法数据加密

版权声明:本文为博主柒晓白(邹涛)原创文章,未经博主允许不得转载,否则追究法律责任。 https://blog.csdn.net/ITBigGod/article/details/88087474

java/web工具类之MD5、AES、Base64算法数据加密

对加密解先理解:

比如:甲乙双方要通信,中间的连接可能被人窃听甚至篡改。解决办法就是把传输的内容进行加密,用密文去传输,这样即使被监听也没办法知道信息的具体内容。

加密时,甲乙双方可以约定一个密码A,甲用A加密,乙用A解密,这就是对称加密

对称加密存在一个问题是:密钥怎么传递给对方?

貌似没解,于是就出现了非对称加密,非对称加密时有两个密钥,就是公钥和私钥。用公钥加密的只能用私钥解密,反之用私钥加密的则只能用公钥解密。这样在流程上有点儿变化了。

原先在对称加密中,密钥没法传递,现在好了,密钥不用传递,因为公钥是公开的,谁都可以拿到。

但是还漏掉了一个问题:虽然篡改不了问题,那我总可以冒名发数据吧?

因为乙的公钥是公开的,那我就可以拿着乙的公钥给乙想发什么就发什么?

乙怎么知道数据甲发过来的呢?答案是用数字签名来验证。

总结:

加密技术通常分为两大类:“对称式"和"非对称式”。
非对称加密:包括RSA DSA RCC,非对称加密是相比对称加密而言的
对称加密:包括AES,DES,3DES。

其次,对应于安全问题的解决办法如下:

数据完整性问题:数据摘要验证
数据保密性问题:对称加密&非对称加密
身份验证问题:数字签名


1.Base64编码加密和解密

将数据转换为不便于识别的数据算是一种最简单的加密了,比如Base64编码。

Base64:属于对称加密算法

Base64是一种能将任意Binary资料用64种字元组合成字串的方法,而这个Binary资料和字串资料彼此之间是可以互相转换的,十分方便。

用处:

Base64这种编码是可逆的,也就是可以加密也可以解密。一般在web开发中常常用来加密图片路径,这种不是很重要又不想被人盗走的,就用这种简单加密。

在这里插入图片描述

JDK1.8以下

使用Java8以下的小伙伴,要使用Base64的编码与解码,就可以使用JDK里sun.misc套件下的BASE64Encoder和BASE64Decoder这两个类别,

用法如下:

	import sun.misc.BASE64Decoder;
	import sun.misc.BASE64Encoder;

	public static void main(String[] args) throws IOException{
		
		//java 8以下 import sun.misc.BASE64Decoder;
	    String text = "这是一段明文";
        byte[] bytes = text.getBytes();
        String encodedStr = encode(bytes);
        byte[] decodedBytes = decode(encodedStr); 
        System.out.println("原文字:"+text);
        System.out.println("加密字段:"+encodedStr);
        System.out.println("解密字段:"+new String(decodedBytes));
        
	}
    public static String encode(byte[] bytes){
        return new BASE64Encoder().encode(bytes);
    }
    public static byte[] decode(String encodeStr) throws IOException{
        return new BASE64Decoder().decodeBuffer(encodeStr);
    }

结果:
在这里插入图片描述

JDK1.8或以上

在目前的Java8中,已经内置Base64的实现类,可以通过java.util.Base64工具类来使用。
非常方便。
用法如下:

public static void main(String[] args) throws IOException{
		
		//Java 8 import java.util.Base64;
		final Base64.Decoder decoder = Base64.getDecoder();
		final Base64.Encoder encoder = Base64.getEncoder();
		
		String text = "这是一段明文";
		System.out.println("原文字:"+text);
		final byte[] textByte = text.getBytes("UTF-8");
		//编码
		String encodedText = encoder.encodeToString(textByte);
		System.out.println("加密字段:"+encodedText);
		//解码
		String jiemi = new String(decoder.decode(encodedText), "UTF-8");
		System.out.println("解密字段:"+jiemi);

效果:
在这里插入图片描述
实际测试编码与解码速度的话,Java 8提供的Base64,要比sun.mis c套件提供的还要快至少11倍,
所以:
在Java上若要使用Base64,推荐Java8的java.util提供的Base64!

2.AES算法加密和解密

AES:也属于对称加密算法

AES加密的明文分组的长度为128位即16字节,密钥长度可以为16,24或者32字节(128,192,256位)。根据密钥的长度,算法被称为AES-128,AES-192或者AE-256。

在这里插入图片描述
用法如下:

package com.zout.crud.utils;


import org.springframework.util.StringUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 
 *@class_name:AesUtil
 *@comments:AES加密工具类
 *@author:邹涛/Zoutao
 *@createtime:2019年3月3日
 */
public class AesUtil {


    /**
     * AES加密
     *
     * @param content
     * @param key
     * @param iv
     * @return
     */
    public static String encrypt(String content, String key, String iv) {
        if (StringUtils.isEmpty(key)) {
            return null;
        }
        if (key.length() != 16) {
            return null;
        }
        String encryptText = "";
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
            byte[] encrypted = cipher.doFinal(content.getBytes());
            encryptText = parseByte2HexStr(encrypted);
        } catch (IllegalBlockSizeException e) {
        } catch (BadPaddingException e) {
        } catch (InvalidKeyException e) {
        } catch (InvalidAlgorithmParameterException e) {
        } catch (NoSuchAlgorithmException e) {
        } catch (NoSuchPaddingException e) {
        }
        return encryptText;
    }

    /**
     * AES解密
     *
     * @param content
     * @param key
     * @param iv
     * @return
     */
    public static String decrypt(String content, String key, String iv) {
        if (StringUtils.isEmpty(key)) {
            return "AES加密KEY为空!";
        }
        if (key.length() != 16) {
            return "AES加密KEY长度必须16位!";
        }
        String decryptText = "";
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
            byte[] byteContent = parseHexStr2Byte(content);
            byte[] original = cipher.doFinal(byteContent);
            decryptText = new String(original);
        } catch (NoSuchAlgorithmException e) {
        } catch (NoSuchPaddingException e) {
        } catch (InvalidAlgorithmParameterException e) {
        } catch (InvalidKeyException e) {
        } catch (BadPaddingException e) {
        } catch (IllegalBlockSizeException e) {
        }
        return decryptText;
    }


    /**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return sb
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return result
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static void main(String[] args) {
        String key = "AkxfGVoMiKDxUiJM";
        String iv = "1841611841611010";
        String content = "root";
        String str = encrypt(content, key, iv);
        System.out.println("源数据:"+content);
        System.out.println("AES加密:"+str);
        System.out.println("AES解密:"+decrypt(str, key, iv));
    }
}

效果:
在这里插入图片描述

MD5加密

MD5全称为信息-摘要算法(哈希算法),是为计算机安全领域的散列函数,用于确保消息的完整性。另外摘要算法还有SHA1,具体请度娘。

MD5是一种单向加密,它的加密不可逆,它将任意长度的字符串,经过算法计算后生成固定长度的数据,一般为16位表示。

MD5算法,是不可逆的,则属于内容摘要。

在这里插入图片描述
用法如下:

package com.zout.utils;

import java.security.MessageDigest;


/**
 * 
 *@class_name:MD5andKL
 *@comments:使用MessageDigest对字符串进行MD5算法的步骤:
 *先将字符串转换成字节数组,在进行MD5算法,最后返回的也是一个字节数组,
 *要我们自己转成32位的字符串或不转。
 *@author:邹涛/Zoutao
 *@createtime:2019年3月3日
 */
public class MD5andKL {  
	
	
	 // MD5加码。32位  
	 public static String MD5(String inStr) {  
	  MessageDigest md5 = null;  
	  try {  
	   md5 = MessageDigest.getInstance("MD5");  
	  } catch (Exception e) {  
	   System.out.println(e.toString());  
	   e.printStackTrace();  
	   return "";  
	  }  
	  char[] charArray = inStr.toCharArray();  
	  byte[] byteArray = new byte[charArray.length];  
	  for (int i = 0; i < charArray.length; i++)  
	   byteArray[i] = (byte) charArray[i];  
	  byte[] md5Bytes = md5.digest(byteArray);  
	  StringBuffer hexValue = new StringBuffer();  
	  for (int i = 0; i < md5Bytes.length; i++) {  
	   int val = ((int) md5Bytes[i]) & 0xff;  
	   if (val < 16)  
	    hexValue.append("0");  
	   hexValue.append(Integer.toHexString(val));  
	  }  
	  
	  return hexValue.toString();  
	 }  
	  
	 // 可逆的加密算法  
	 public static String KL(String inStr) {  
	  // String s = new String(inStr);  
	  char[] a = inStr.toCharArray();  
	  for (int i = 0; i < a.length; i++) {  
	   a[i] = (char) (a[i] ^ 't');  
	  }  
	  String s = new String(a);  
	  return s;  
	 }  
	  
	 // 加密后解密  
	 public static String JM(String inStr) {  
	  char[] a = inStr.toCharArray();  
	  for (int i = 0; i < a.length; i++) {  
	   a[i] = (char) (a[i] ^ 't');  
	  }  
	  String k = new String(a);  
	  return k;  
	 }  
	   
	 // 测试主函数  
	 public static void main(String args[]) {  
	  String s = new String("123456");  
	  System.out.println("原始:" + s);  
	  System.out.println("MD5后:" + MD5(s));  
	  System.out.println("MD5后再加密:" + KL(MD5(s)));  
	  System.out.println("解密为MD5后的:" + JM(KL(MD5(s)))); 
	  
	 }  
	}  

效果:
在这里插入图片描述
在本工具类中,首先明文采用MD5加密,又加了一层新的加密KL,是可逆的。但是MD5不可逆。
不想要可以直接去掉KL。

4.项目应用总结:

  1. 加密算法是可逆的,用来对敏感数据进行保护。散列算法(签名算法、哈希算法)是不可逆的,主要用于身份验证。
  2. 对称加密算法使用同一个密匙加密和解密,速度快,适合给大量数据加密。对称加密客户端和服务端使用同一个密匙,存在被抓包破解的风险。
  3. 非对称加密算法使用公钥加密,私钥解密,私钥签名,公钥验签。安全性比对称加密高,但速度较慢。非对称加密使用两个密匙,服务端和客户端密匙不一样,私钥放在服务端,黑客一般是拿不到的,安全性高。
  4. Base64不是安全领域下的加解密算法,只是一个编码算法,通常用于把二进制数据编码为可写的字符形式的数据,特别适合在http,mime协议下的网络快速传输数据。UTF-8和GBK中文的Base64编码结果是不同的。采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到,但这种方式很初级,很简单。Base64可以对图片文件进行编码传输。
  5. MD5标准密钥长度128位(128位是指二进制位。二进制太长,所以一般都改写成16进制,每一位16进制数可以代替4位二进制数,所以128位二进制数写成16进制就变成了128/4=32位。16位加密就是从32位MD5散列中把中间16位提取出来);sha1标准密钥长度160位(比MD5摘要长32位),Base64转换后的字符串理论上将要比原来的长1/3。
  6. MD5可以用来加密用户密码,AES可以用来加密一些可翻转的数据,base64可以用来加密图片文件数据。

参考文章:

https://www.cnblogs.com/huqiaoblog/p/7519600.html?utm_source=debugrun&utm_medium=referral
https://www.cnblogs.com/sunxuchu/p/5483956.html


加密算法这一块,不需要深入研究,只需要拿来用即可。直接复制代码即可使用。

猜你喜欢

转载自blog.csdn.net/ITBigGod/article/details/88087474