Base64 MD5 AES RSA JAVA加密

常见的加密解密算法,AES、RSA、Base64、MD5,别人的例子很多,自己亲测的,才是自己掌握的。

Base64

        try {
            BASE64Encoder base64Encoder = new BASE64Encoder();
            //加密
            String encodeString = base64Encoder.encode("生死看淡,不服来干!".getBytes("utf-8"));
            System.out.println(encodeString);
            //解密
            BASE64Decoder base64Decoder = new BASE64Decoder();
            String source = new String(base64Decoder.decodeBuffer(encodeString), "utf-8");
            System.out.println(source);
        } catch (Exception e) {
            e.printStackTrace();
        }
       //输出:
       55Sf5q2755yL5reh77yM5LiN5pyN5p2l5bmy77yB
	   生死看淡,不服来干!
使用场景:

Base64是一种编码的转换,编码规则是公开的,所以不能用做加密用途,它的主要作用不在于安全性,而在于让内容能在网络间无错的传输。比如URL里面的key-value包含了等号,或者用其它加密算法加密后的报文出现乱码或者不友好的特殊符号,这时候就可以使用Base64编码。

MD5

import org.springframework.util.DigestUtils;

/**
 * @Author 哆啦的哆啦美
 * @Description MD5加密与验证
 * @Date 2019/6/17 15:51
 * @Modify
 */
public class MD5Util {

    public static void main(String[] args) {
        try {
            String sign = md5("生死看淡,不服就干!");
            System.out.println("解密后:" + sign);
            System.out.println(verify("生死看淡,不服就干!", sign));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * MD5方法
     *
     * @param content 明文
     * @return 密文
     * @throws Exception
     */
    public static String md5(String content) throws Exception {
        //加密后的字符串
        String encodeStr = DigestUtils.md5DigestAsHex(content.getBytes("utf-8"));
        return encodeStr;
    }

    /**
     * MD5验证方法
     *
     * @param content 明文
     * @param sign    密文
     * @return true/false
     * @throws Exception
     */
    public static boolean verify(String content, String sign) throws Exception {
        //根据传入的密钥进行验证
        String md5Text = md5(content);
        if (md5Text.equalsIgnoreCase(sign)) {
            System.out.println("MD5验证通过");
            return true;
        }
        return false;
    }
}
输出内容:
解密后:11389f5464ddc5c00b854e1ff7bf347d
MD5验证通过
true
使用场景:

MD5是不可逆的,即加密后的字符串,是无法反推出原文是什么的,这决定了MD5通常用于加密验证,比如把用户密码进行MD5加密后存进数据库,要验证用户密码的时候也是进行MD5加密后再进行对比,这样子就算数据库被攻破,用户的密码也不会被泄露出去,因为无法解密。
此外,还经常用户保证数据的完整性,比如通过自己定义的一些规则,对报文进行DM5加密,服务器收到报文后,通过同样的规则进行加密,如果得到不同样的结果,则该报文被修改过,是不可信的。
网上通常的加密方法有:MD5(MD5(用户名+用户密码)+MD5(KEY+项目名+公司名))
这只是个例子,定义的方法可以千变万化,看个人习惯。

AES

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

/**
 * @Author 哆啦的哆啦美
 * @Description AES加密解密
 * @Date 2019/6/17 14:04
 */
public class AESUtil {
    public static void main(String[] args) {
        byte[] encrypt1 = AESUtil.encrypt("生死看淡,不服来战!", "123456");
        byte[] encrypt2 = AESUtil.encrypt("生死看淡,不服来战!", "654321");
        System.out.println("加密1:" + encrypt1);
        System.out.println("加密2:" + encrypt2);
        System.out.println("解密1:" + AESUtil.decrypt(encrypt1, "123456"));
        System.out.println("解密2:" + AESUtil.decrypt(encrypt2, "654321"));
        try {
            System.out.println("密码错误:" + AESUtil.decrypt(encrypt2, "666666"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * AES加密字符串
     *
     * @param content  需要被加密的字符串
     * @param password 加密需要的密码
     * @return 密文
     */
    public static byte[] encrypt(String content, String password) {
        try {
            // 创建AES的Key生产者
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            // 利用用户密码作为随机数初始化出128位的key生产者
            keyGenerator.init(128, new SecureRandom(password.getBytes()));
            // 根据用户密码,生成一个密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 返回基本编码格式的密钥,如果此密钥不支持编码,则返回null
            byte[] enCodeFormat = secretKey.getEncoded();
            // 转换为AES专用密钥
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            // 创建密码器
            Cipher cipher = Cipher.getInstance("AES");
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //加密内容转字节类型
            byte[] byteContent = content.getBytes("utf-8");
            //加密
            byte[] result = cipher.doFinal(byteContent);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decrypt(byte[] content, String password) {
        try {
            // 创建AES的Key生产者
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            // 利用用户密码作为随机数初始化出128位的key生产者
            kgen.init(128, new SecureRandom(password.getBytes()));
            // 根据用户密码,生成一个密钥
            SecretKey secretKey = kgen.generateKey();
            // 返回基本编码格式的密钥,如果此密钥不支持编码,则返回null
            byte[] enCodeFormat = secretKey.getEncoded();
            // 转换为AES专用密钥
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            // 创建密码器
            Cipher cipher = Cipher.getInstance("AES");
            // 初始化为解密模式的密码器
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] result = cipher.doFinal(content);
            // 明文
            return new String(result, "utf-8"); 
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

//输出:
加密1[B@546a03af
加密2[B@721e0f4f
解密1:生死看淡,不服来战!
解密2:生死看淡,不服来战!
密码错误:null
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
使用场景:

AES 是一种对称加密算法,即加密和解密使用同一个密钥的加密方式。由于它的加密是可逆的,通常用来加密一些不想被别人看到的报文,只有持有密码的人才能看到,其他人无法解密。
AES的算法安全性好高,没有密码几乎是无法破解的,但是当它的密码是动态的,需要在网络上传输的时候,密码保存与传输就存在安全问题。所以它经常与非对称加密算法RSA配合着使用,可往下看RSA加密算法。

RSA

package com.xuliubin.springbase.utils;

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

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author 哆啦的哆啦美
 * @Description RSA加密解密
 * @Date 2019/6/17 14:04
 * @Modify
 */
public class RSAUtil {

    //用于封装随机产生的公钥与私钥
    private static Map<Integer, String> keyMap = new HashMap<Integer, String>();
    private static BASE64Decoder base64Decoder = new BASE64Decoder();
    private static BASE64Encoder base64Encoder = new BASE64Encoder();

    public static void main(String[] args) {
        try {
            //生成公钥和私钥
            genKeyPair();
            //加密字符串
            String message = "生死看淡,不服来干!";
            System.out.println("随机生成的公钥为:" + keyMap.get(0));
            System.out.println("随机生成的私钥为:" + keyMap.get(1));
            String messageEn = encrypt(message, keyMap.get(0));
            System.out.println("加密前的字符串为:" + message);
            System.out.println("加密后的字符串为:" + messageEn);
            String messageDe = decrypt(messageEn, keyMap.get(1));
            System.out.println("还原后的字符串为:" + messageDe);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * RSA加密字符串
     *
     * @param content   需要被加密的字符串
     * @param publicKey Base64编码的公钥
     * @return 密文
     */
    public static String encrypt(String content, String publicKey) throws Exception {

        //base64解码的公钥
        byte[] decodedKey = base64Decoder.decodeBuffer(publicKey);
        //RSA公钥对象
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decodedKey));
        // 创建RSA密码器
        Cipher cipher = Cipher.getInstance("RSA");
        // 初始化为加密模式的密码器
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);

        //加密并转为Base64编码
        String outStr = base64Encoder.encode(cipher.doFinal(content.getBytes("UTF-8")));
        return outStr;
    }

    /**
     * RSA解密字符串
     *
     * @param content    Base64编码的密文
     * @param privateKey Base64编码的私钥
     * @return 明文
     */
    public static String decrypt(String content, String privateKey) throws Exception {
        BASE64Decoder base64Decoder = new BASE64Decoder();
        //Base64解码后的密文
        byte[] inputByte = base64Decoder.decodeBuffer(content);
        //Base64解码后的私钥
        byte[] decodedKey = base64Decoder.decodeBuffer(privateKey);
        //RSA密钥对象
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
        // 创建RSA密码器
        Cipher cipher = Cipher.getInstance("RSA");
        // 初始化为解密模式的密码器
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte), "utf-8");
        return outStr;
    }

    /**
     * 获取秘钥对
     *
     * @throws Exception
     */
    public static void genKeyPair() throws Exception {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器,密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 得到公钥Base64编码的字符串
        String publicKeyString = new String(base64Encoder.encodeBuffer(publicKey.getEncoded()));
        // 得到私钥Base64编码的字符串
        String privateKeyString = new String(base64Encoder.encodeBuffer((privateKey.getEncoded())));
        // 将公钥和私钥保存到Map
        keyMap.put(0, publicKeyString);  //0表示公钥
        keyMap.put(1, privateKeyString);  //1表示私钥
    }
}
//输出:
	随机生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaX9W3UuabdK0f9C2yK5jYNG8D6dFhWDK8KID4
	t0S/2kwwF3dPEQxt0mvHAhBgJ1BKNtZzZYOqI6KO3e+rqRJwKX8/l8t6/UnKZhg/iYhBoo8ENR1s
	Ytphdj57lnfvQ/2Yj5da6cPXNf7bZiex1GiWIfrsCveHc/LUZYeP6YASQwIDAQAB
	
	随机生成的私钥为:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJpf1bdS5pt0rR/0LbIrmNg0bwPp
	0WFYMrwogPi3RL/aTDAXd08RDG3Sa8cCEGAnUEo21nNlg6ojoo7d76upEnApfz+Xy3r9ScpmGD+J
	iEGijwQ1HWxi2mF2PnuWd+9D/ZiPl1rpw9c1/ttmJ7HUaJYh+uwK94dz8tRlh4/pgBJDAgMBAAEC
	gYBt+P2HpnAPqJO4Yru25GXzB49aa1Q0k584+WW/SNeaEMobrGvbEJsZFUCgObEuvnLtG5m0BUpB
	hzdDrYkScdRmpU8De7POvsI5xeDuR20cw573cQkU87txi8yXT2xR6ZgDePYN+h5nSkPi63zLbDBk
	widhX/tPeThrotPspeT20QJBAM3rLRBoArvJVD+v8ScPE/wGQm0qYbKAEn91KjjuQbwDVN8Lsikr
	9HXocU88+VsHQ3EdwUShvn2QUI0//DsITRsCQQC/622pzOD09GobqtAE/GpJXlZtsktyrfzqak7C
	vt1AxYOzvUtqCXRB9vHQ84LIER/KqYcYcxoTCSjXm4jyN2n5AkBeQrluOS6HJ7IZNUD+0DgltffS
	YQQ34ciV79xUEzykBCJlt8Tmc+iD0NONoivDL5//t88wy5mXgOhewFuF6lbhAkEAmTe6YCI5wjXS
	9G2lDyX5MMPI2mDKTS7MSNVANces2cYWBAvuxiPwFa2xlnCiC1loeSJowUM7INFiMudwKHfG+QJB
	AMs4FLQlr/ePCafHkn5QZbPVzm8txo6SqEgj8DpLf42kJP/HeV9rso4ul+QyyRnyzNZ0y/CGWdi3
	umoDB/nXWWE=
	
	加密前的字符串为:生死看淡,不服来干!
	加密后的字符串为:TPZbjRhJHLefpFb1Tbics0LKbgW5tIPsT5DhX6cSln0nOEDLwjHvS7kh9YDmedNbOE8NkQFdqCCx
	YgV1tVherVnKkFxEgP8uVdXocPZJZ/DMLPmkk1ZlpotLCq7xCGG7aT4c9eZBEixF3+lZra2G+aUI
	juqdUgfKBrN4m+KcUtQ=
	还原后的字符串为:生死看淡,不服来干!
使用场景:

上面说到AES算法经常会配合着RAS一起使用,它们2个的安全性都很高,但是在性能方面AES会好很多,特别是加密的内容越大,RAS就越吃不消,另一方面AES的密码又存在会泄露的不安全,而RAS的公钥是不怕泄露,所以有了结合使用的方案。
我理解的具体场景如下:
客户端需要向服务端发送请求,首先用AES加密算法把所有的内容加密起来,这样子只要保证AES的密码安全给到服务器,那么报文的内容就安全了。
怎么保证密码安全给到服务器呢?首先客户端需要向服务器请求一个RAS的加密公钥,拿到公钥后用于对AES密码进行加密,这样子世界上除了拥有秘钥的服务器,其它人都休想知道AES的密码是多少,也就无法解开报文的内容了。最后安全地把AES加密的报文和RSA加密的密码,一起发给服务器。
以下再贴一下,Vue里面进行RAS加密的代码。(BTW,即使是相同的公钥和相同的加密内容,加密后的结果都是不一样的,但解密出来一样)

	   import { JSEncrypt } from 'jsencrypt'
       var publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaX9W3UuabdK0f9C2yK5jYNG8D6dFhWDK8KID4\n" +
          "t0S/2kwwF3dPEQxt0mvHAhBgJ1BKNtZzZYOqI6KO3e+rqRJwKX8/l8t6/UnKZhg/iYhBoo8ENR1s\n" +
          "Ytphdj57lnfvQ/2Yj5da6cPXNf7bZiex1GiWIfrsCveHc/LUZYeP6YASQwIDAQAB";
        var privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJpf1bdS5pt0rR/0LbIrmNg0bwPp\n" +
          "0WFYMrwogPi3RL/aTDAXd08RDG3Sa8cCEGAnUEo21nNlg6ojoo7d76upEnApfz+Xy3r9ScpmGD+J\n" +
          "iEGijwQ1HWxi2mF2PnuWd+9D/ZiPl1rpw9c1/ttmJ7HUaJYh+uwK94dz8tRlh4/pgBJDAgMBAAEC\n" +
          "gYBt+P2HpnAPqJO4Yru25GXzB49aa1Q0k584+WW/SNeaEMobrGvbEJsZFUCgObEuvnLtG5m0BUpB\n" +
          "hzdDrYkScdRmpU8De7POvsI5xeDuR20cw573cQkU87txi8yXT2xR6ZgDePYN+h5nSkPi63zLbDBk\n" +
          "widhX/tPeThrotPspeT20QJBAM3rLRBoArvJVD+v8ScPE/wGQm0qYbKAEn91KjjuQbwDVN8Lsikr\n" +
          "9HXocU88+VsHQ3EdwUShvn2QUI0//DsITRsCQQC/622pzOD09GobqtAE/GpJXlZtsktyrfzqak7C\n" +
          "vt1AxYOzvUtqCXRB9vHQ84LIER/KqYcYcxoTCSjXm4jyN2n5AkBeQrluOS6HJ7IZNUD+0DgltffS\n" +
          "YQQ34ciV79xUEzykBCJlt8Tmc+iD0NONoivDL5//t88wy5mXgOhewFuF6lbhAkEAmTe6YCI5wjXS\n" +
          "9G2lDyX5MMPI2mDKTS7MSNVANces2cYWBAvuxiPwFa2xlnCiC1loeSJowUM7INFiMudwKHfG+QJB\n" +
          "AMs4FLQlr/ePCafHkn5QZbPVzm8txo6SqEgj8DpLf42kJP/HeV9rso4ul+QyyRnyzNZ0y/CGWdi3\n" +
          "umoDB/nXWWE=";
        // 新建JSEncrypt对象
        let encryptor = new JSEncrypt()
        // 设置公钥
        encryptor.setPublicKey(publicKey)
        // 对密码进行加密
        let rsaPassWord = encryptor.encrypt('生死看淡,不服来干!')
        console.log('加密后字符串' + rsaPassWord);

        var decrypt = new JSEncrypt();
        decrypt.setPrivateKey(privateKey);
        //解密数据
        var uncrypted = decrypt.decrypt(rsaPassWord);
        console.log('解密后字符串:' + uncrypted)

//输出内容:
加密后字符串Ayqvj167sewOze2ViNZgraiaxVc+wb0p1fF80XJ0bOo+5njlt73CLLtFBE/8n1cK2WnHTQbIOpn3/ZnZkkGhBQ7khRZ4h0IH+vFvmNIO9waw9FwETq193V12b3VgSimP2lBjte1WeBcYRxKP+hyBDq2CK2tmdGXENAOjbxAblgg=
解密后字符串:生死看淡,不服来干!

仅仅是个人浅薄见解,不妥之处,还望指出。

你可能感兴趣的:(utils)