Java加密算法—对称加密(DES、AES)

目录

  • 1、概述
  • 2、加密模式
    • 2.1 ECB
    • 2.2 CBC
  • 3、填充模式
  • 4、对称加密、解密实现

1、概述

对称加密就是采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,也称为单密钥加密。

比如:凯撒加密就可以认为是一种对称加密,将偏移量看作密钥,加密和解密都用的是相同的偏移量(密钥)

  • 常见加密算法:

    • DES : Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美 国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。
    • AES : Advanced Encryption Standard, 高级加密标准 .在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
  • 特点:

    • 加密速度快, 可以加密大文件。
    • 密文可逆, 一旦密钥文件泄漏, 就会导致数据暴露。
    • 加密后编码表找不到对应字符, 出现乱码,一般结合Base64使用。

2、加密模式

2.1 ECB

ECB : Electronic codebook, 电子密码本. 需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密。
Java加密算法—对称加密(DES、AES)_第1张图片

  • 优点 : 可以并行处理加密数据,速度快。
  • 缺点 : 同样的原文生成同样的密文, 不能很好的保护数据。

2.2 CBC

CBC : Cipher-block chaining, 密码块链接. 每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。
Java加密算法—对称加密(DES、AES)_第2张图片

优点 : 同样的原文生成的密文不一样。
缺点 : 串行处理数据,速度较慢。

3、填充模式

当需要按块处理的数据, 数据长度不符合块处理需求时, 按照一定的方法填充满块长的规则,分为NoPaddingPKCS5Padding

NoPadding:

  • 不填充。
  • 在DES加密算法下, 要求原文长度必须是8byte的整数倍。
  • 在AES加密算法下, 要求原文长度必须是16byte的整数倍。

PKCS5Padding:

  • 数据块的大小为8位, 不够就补足

注意:

  • 默认情况下, 加密模式和填充模式为 : ECB/PKCS5Padding
  • 如果使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new IvParameterSpec(key.getBytes());

加密模式和填充模式创建模式:

AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)

4、对称加密、解密实现

将对称加密的DES和AES进行封装处理,达到一套代码实现两种加密方式,结合了加密模式和填充模式的应用,代码可以直进行使用。。

代码实现:

public class SymmetryTest {
    private final static String DES = "DES";

    private final static String AES = "AES";

    /**
     * 设置为CBC加密模式,默认情况下ECB比CBC更高效
     */
    private final static String CBC = "/CBC/PKCS5Padding";

    public static void main(String[] args) {
        // 对称加密 密文
        String input = "key=85CD019515D14B91AD942787532314FF&startTime=1629431243245&endTime=1660967243244";
        // DES加密算法,key的大小必须是8个字节
        String desKey = "12345678";
        // AES加密算法,key的大小必须是16个字节
        String aesKey = "1234567812345678";
		String encryptDes = encryptBySymmetry(input, desKey, SymmetryTest.DES, true);
        System.out.println("DES加密:" + encryptDes);
        String des = decryptBySymmetry(encryptDes, desKey, SymmetryTest.DES, true);
        System.out.println("DES解密:" + des);

        System.out.println("\n==============================================\n");

        String encryptAes = encryptBySymmetry(input, aesKey, SymmetryTest.AES);
        System.out.println("AES加密:" + encryptAes);
        String aes = decryptBySymmetry(encryptAes, aesKey, SymmetryTest.AES);
        System.out.println("AES解密:" + aes);
    }

    /**
     * 对称加密
     *
     * @param input     : 密文
     * @param key       : 密钥
     * @param algorithm : 类型:DES、AES
     * @return
     */
    public static String encryptBySymmetry(String input, String key, String algorithm) {
        return encryptBySymmetry(input, key, algorithm, false);
    }

    /**
     * 对称解密
     *
     * @param input     : 密文
     * @param key       : 密钥
     * @param algorithm : 类型:DES、AES
     * @return
     */
    public static String decryptBySymmetry(String input, String key, String algorithm) {
        return decryptBySymmetry(input, key, algorithm, false);
    }

    /**
     * 对称加密数据
     *
     * @param input     : 原文
     * @param key       : 密钥
     * @param algorithm : 类型:DES、AES
     * @param cbc       : CBC加密模式:同样的原文生成的密文不一样,串行进行,加密使用CBC解密也需要CBC
     * @return : 密文
     * @throws Exception
     */
    public static String encryptBySymmetry(String input, String key, String algorithm, Boolean cbc) {
        try {
            // 根据加密类型判断key字节数
            checkAlgorithmAndKey(key, algorithm);

            // CBC模式
            String transformation = cbc ? algorithm + CBC : algorithm;
            // 获取加密对象
            Cipher cipher = Cipher.getInstance(transformation);
            // 创建加密规则
            // 第一个参数key的字节
            // 第二个参数表示加密算法
            SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);

            // ENCRYPT_MODE:加密模式
            // DECRYPT_MODE: 解密模式
            // 初始化加密模式和算法
            // 默认采用ECB加密:同样的原文生成同样的密文,并行进行
            // CBC加密:同样的原文生成的密文不一样,串行进行
            if (cbc) {
                // 使用CBC模式
                IvParameterSpec iv = new IvParameterSpec(key.getBytes());
                cipher.init(Cipher.ENCRYPT_MODE, sks, iv);
            } else {
                cipher.init(Cipher.ENCRYPT_MODE, sks);
            }

            // 加密
            byte[] bytes = cipher.doFinal(input.getBytes());

            // 输出加密后的数据
            return Base64.encode(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("加密失败!");
        }
    }

    /**
     * 对称解密
     *
     * @param input     : 密文
     * @param key       : 密钥
     * @param algorithm : 类型:DES、AES
     * @param cbc       : CBC加密模式:同样的原文生成的密文不一样,串行进行,加密使用CBC解密也需要CBC
     * @throws Exception
     * @return: 原文
     */
    public static String decryptBySymmetry(String input, String key, String algorithm, Boolean cbc) {
        try {
            // 根据加密类型判断key字节数
            checkAlgorithmAndKey(key, algorithm);

            // CBC模式
            String transformation = cbc ? algorithm + CBC : algorithm;

            // 1,获取Cipher对象
            Cipher cipher = Cipher.getInstance(transformation);
            // 指定密钥规则
            SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
            // 默认采用ECB加密:同样的原文生成同样的密文
            // CBC加密:同样的原文生成的密文不一样
            if (cbc) {
                // 使用CBC模式
                IvParameterSpec iv = new IvParameterSpec(key.getBytes());
                cipher.init(Cipher.DECRYPT_MODE, sks, iv);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, sks);
            }
            // 3. 解密,上面使用的base64编码,下面直接用密文
            byte[] bytes = cipher.doFinal(Base64.decode(input));
            //  因为是明文,所以直接返回
            return new String(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("解密失败!");
        }
    }

    private static void checkAlgorithmAndKey(String key, String algorithm) {
        // 根据加密类型判断key字节数
        int length = key.getBytes().length;
        boolean typeEnable = false;
        if (DES.equals(algorithm)) {
            typeEnable = length == 8;
        } else if (AES.equals(algorithm)) {
            typeEnable = length == 16;
        } else {
            throw new RuntimeException("加密类型不存在");
        }
        if (!typeEnable) {
            throw new RuntimeException("加密Key错误");
        }
    }
}

效果:

Java加密算法—对称加密(DES、AES)_第3张图片

你可能感兴趣的:(数据加密应用,java,安全,开发语言)