【Java工具类】对称加密之整合AES、DES算法加解密工具类

  • 对称加密算法只是为了区分非对称加密算法。特点就是加密是加密解密使用相同的密钥,而非对称加密加密和解密时使用的密钥不一样
    • 对称加密的密钥交换时可以使用非对称加密,这有效保护密钥的安全。
    • 非对称加密加密和解密密钥不同,安全性高,但加解密的速度很慢,不适合对大数据加密。而对称加密加密速度快,因此混合使用最好。

常用的对称加密算法有:AES和DES.

  • DES:比较老的算法,一共有三个参数入口(原文,密钥,加密模式)。而3DES只是DES的一种模式,是以DES为基础更安全的变形,对数据进行了三次加密,也是被指定为AES的过渡算法。
  • AES:高级加密标准,新一代标准,加密速度更快,安全性更高(优先选择)
import org.junit.Test;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

public class SymmetricEncryptionUtil {
    
    
    private static final String AES = "AES";
    private static final String DES = "DES";
    /**
     * AES密钥
     */
    private static final String AES_KEY = "FFC22E80F61AB7295C02493856B4C520";

    /**
     * AES模式
     */
    private static final String AES_MODE = "AES/ECB/PKCS5Padding";


    /**
     * DES密钥: 加解密用到的秘钥-getBytes().length即字节的长度必须大于等于8,否则报异常java.security.InvalidKeyException: Wrong key size
     */
    private static final String DES_KEY = "*%#@()^&";
    /**
     * DES模式
     * "AES/ECB/PKCS5Padding"在加密和解密时必须相同,可以直接写”AES”,这样就是使用默认模式分别的意思为:AES是加密算法,ECB是工作模式,PKCS5Padding是填充方式。
     */
    private static final String DES_MODE = "DES/ECB/PKCS5Padding";


    /**
     * 使用AES对字符串加密
     *
     * @param str utf8编码的字符串
     * @param key 密钥(16字节)
     * @return 加密结果
     * @throws Exception
     */
    public static String aesEncrypt(String str, String key) throws Exception {
    
    
        if (str == null || key == null) {
    
    
            return null;
        }

        //AES/ECB/PKCS5Padding在加密和解密时必须相同
        Cipher cipher = Cipher.getInstance(AES_MODE);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES));
        byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));

        //使用base64编码
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 使用AES对数据解密
     *
     * @param base64Encoder base64编码后的字符串
     * @param key           密钥(16字节)
     * @return 解密结果
     * @throws Exception
     */
    public static String aesDecrypt(String base64Encoder, String key) throws Exception {
    
    
        if (base64Encoder == null || key == null) {
    
    
            return null;
        }

        SecureRandom random = new SecureRandom();
        Cipher cipher = Cipher.getInstance(AES_MODE);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES), random);

        //使用base64解码
        byte[] base64DecoderByte = Base64.getDecoder().decode(base64Encoder);
        return new String(cipher.doFinal(base64DecoderByte), StandardCharsets.UTF_8);
    }


    /**
     * 使用DES对字符串加密
     *
     * @param str utf8编码的字符串
     * @param key 密钥(56位,7字节)
     * @return 加密结果
     * @throws Exception
     */
    public static String desEncrypt(String str, String key) throws Exception {
    
    
        if (str == null || key == null) {
    
    
            return null;
        }

        SecureRandom random = new SecureRandom();
        Cipher cipher = Cipher.getInstance(DES_MODE);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES), random);
        byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));

        //使用base64编码
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 使用DES对数据解密
     *
     * @param base64Encoder base64编码后的字符串
     * @param key           密钥(16字节)
     * @return 解密结果
     * @throws Exception
     */
    public static String desDecrypt(String base64Encoder, String key) throws Exception {
    
    
        if (base64Encoder == null || key == null) {
    
    
            return null;
        }
        Cipher cipher = Cipher.getInstance(DES_MODE);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES));
        //使用base64解码
        byte[] base64DecoderByte = Base64.getDecoder().decode(base64Encoder);

        return new String(cipher.doFinal(base64DecoderByte), StandardCharsets.UTF_8);
    }


    /**
     * 测试AES算法
     *
     * @throws Exception
     */
    @Test
    public void main1() throws Exception {
    
    
        String str = "你好,张三!";
        System.out.println("原文:" + str);
        System.out.println("密钥:" + AES_KEY);

        String aesEncrypt = aesEncrypt(str, AES_KEY);
        System.out.println("加密后:" + aesEncrypt);

        String aesDecrypt = aesDecrypt(aesEncrypt, AES_KEY);
        System.out.println("解密后:" + aesDecrypt);
    }


    /**
     * 测试DES算法
     *
     * @throws Exception
     */
    @Test
    public void main2() throws Exception {
    
    
        String str = "你好,张三!";
        System.out.println("原文:" + str);
        System.out.println("密钥:" + DES_KEY);

        String aesEncrypt = desEncrypt(str, DES_KEY);
        System.out.println("加密后:" + aesEncrypt);

        String aesDecrypt = desDecrypt(aesEncrypt, DES_KEY);
        System.out.println("解密后:" + aesDecrypt);
    }
}

执行结果

```java
//main1
原文:你好,张三!
密钥:FFC22E80F61AB7295C02493856B4C520
加密后:Vlm7AY5VxhiOc5QSZe5Szga2oN2+AMpMDyHU9tYktFw=
解密后:你好,张三!

//main2
原文:你好,张三!
密钥:*%#@()^&
加密后:STDcjuovhcYOwV/tFmrvPH25wWw6o48M
解密后:你好,张三!

AES算法的所有参数都是字节码的(包括密钥)。因此字符串字符需要转换成字节码后进行加密

  • 参数:”AES/ECB/PKCS5Padding”加密和解密时必须相同,可以直接写”AES”,这样就是使用默认模式。分别的意思为:AES是加密算法,ECB是工作模式,PKCS5Padding是填充方式

AES是分组加密算法,也称块加密。每一组16字节。这样明文就会分成多块。当有一块不足16字节时就会进行填充。一共有四种工作模式:

  • ECB 电子密码本模式:相同的明文块产生相同的密文块,容易并行运算,但也可能对明文进行攻击。
  • CBC 加密分组链接模式:一块明文加密后和上一块密文进行链接,不利于并行,但安全性比ECB好,是SSL,IPSec的标准。
  • CFB 加密反馈模式:将上一次密文与密钥运算,再加密。隐藏明文模式,不利于并行,误差传递。
  • OFB 输出反馈模式:将上一次处理过的密钥与密钥运算,再加密。隐藏明文模式,不利于并行,有可能明文攻击,误差传递。

PKCS5Padding的填充方式是差多少字节就填数字多少;刚好每一不足16字节时,那么就会加一组填充为16.还有其他填充模式【Nopadding,ISO10126Padding】(不影响算法,加密解密时一致就行)。

猜你喜欢

转载自blog.csdn.net/qq877728715/article/details/115214433
今日推荐