Java 常用加密算法(二)---对称加密(DES/3DES(TripleDES)/AES)

Java 常用加密算法(二)---对称加密(DES/3DES(TripleDES)/AES)

基于“对称密钥”的加密算法主要有DES、3DES(TripleDES)、AES、RC2、RC4、RC5和Blowfish等。

代码中用到的Base64与BouncyCastleProvider的jar包可在本文末尾下载源码,从源码获取jar包。

  1. DES
    DES算法全称为Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。
    五种分组模式:EBC模式、CBC模式、CFB模式、OFB模式、CTR模式。
    其中CTR 模式被广泛用于 ATM 网络安全和 IPSec应用中,相对于其它模式而言,CRT模式具有如下特点:
    ■硬件效率:允许同时处理多块明文 / 密文。
    ■ 软件效率:允许并行计算,可以很好地利用 CPU 流水等并行技术。
    ■ 预处理:算法和加密盒的输出不依靠明文和密文的输入,因此如果有足够的保证安全的存储器,加密算法将仅仅是一系列异或运算,这将极大地提高吞吐量。
    ■ 随机访问:第 i 块密文的解密不依赖于第 i-1 块密文,提供很高的随机访问能力
    ■ 可证明的安全性:能够证明 CTR 至少和其他模式一样安全(CBC, CFB, OFB, ...)
    ■ 简单性:与其它模式不同,CTR模式仅要求实现加密算法,但不要求实现解密算法。对于 AES 等加/解密本质上不同的算法来说,这种简化是巨大的。
    ■ 无填充,可以高效地作为流式加密使用。
    在Java进行DES、3DES和AES三种对称加密算法时,常采用的是NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充。
    示例:

/**
 * DES加密工具类
 * @author mazaiting
 */
public class DESUtil {
    /**
     * 算法名称
     */
    public static final String KEY_ALGORITHM = "DES";
    /**
     * 算法名称/加密模式/填充方式
     * DES的四种工作模式:ECB(电子密码本)、CBC(加密分组链接)、
     * CFB(加密反馈模式)、OFB(输出反馈)
     * 当前无填充的情况:
     *      加密数据必须为8的倍数,密钥输入必须为16的倍数
     *  使用
        String source = "abcdefgh";// 为8位的倍数
        String key = "A1B2C3D4E5F60708";// 为16位的倍数
        
        String encryptData = DESUtil.encrypt(source, key);
        System.out.println("加密后: " + encryptData);
        
        String decryptData = DESUtil.decrypt(encryptData, key);
        System.out.println("解密后: " + decryptData);
     */
    public static final String CIPHER_ALGORITHM_DES_ECB_NOPADDING = "DES/ECB/NoPadding";
    /**
     * DES/CBC/PKCS5Padding
     * PKCS5Padding填充时:
     *      加密数据无位数控制,密钥输入必须为16的倍数
     *  使用
        String source = "abcdefgh";// 无需控制位数
        String key = "A1B2C3D4E5F60708";// 为16位的倍数
        
        String encryptData = DESUtil.encrypt(source, key);
        System.out.println("加密后: " + encryptData);
        
        String decryptData = DESUtil.decrypt(encryptData, key);
        System.out.println("解密后: " + decryptData);
        
     */
    public static final String CIPHER_ALGORITHM_DES_ECB_PKCS5_PADDING = "DES/ECB/PKCS5Padding";
    
    /**
     * 加密数据
     * @param data 待加密的数据--8位
     * @param key 密钥--16位
     * @return 加密后的数据
     */
    public static String encrypt(String data, String key) {
        try {
            // 获得一个密钥
            Key deskey = keyGenerator(key);
            // 实例化一个Cipher(密码)对象,用于完成加密操作
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_DES_ECB_PKCS5_PADDING);
            SecureRandom random = new SecureRandom();
            // 初始化Cipher对象,设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
            byte[] bytes = data.getBytes();
            // 执行加密操作
            byte[] results = cipher.doFinal(bytes);
            return Base64.encodeBase64String(results);
        } catch (InvalidKeyException e) {
            return "无效KEY"; // 无效KEY
        } catch (NoSuchAlgorithmException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (InvalidKeySpecException e) {
            return "无效KeySpec"; // 无效KeySpec
        } catch (NoSuchPaddingException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (IllegalBlockSizeException e) {
            return "无效字节"; // 无效字节
        } catch (BadPaddingException e) {
            return "解析异常"; // 解析异常
        }
    }

    /**
     * 解密数据
     * @param data 待解密数据
     * @param key 密钥
     * @return 解密后的数据
     */
    public static String decrypt(String data, String key) {
        try {
            Key desKey = keyGenerator(key);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_DES_ECB_PKCS5_PADDING);
            // 初始化Cipher对象,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, desKey);
            // 执行解密操作
            byte[] decBytes = cipher.doFinal(Base64.decodeBase64(data));
            return new String(decBytes,"UTF-8");
        } catch (InvalidKeyException e) {
            return "无效KEY"; // 无效KEY
        } catch (NoSuchAlgorithmException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (InvalidKeySpecException e) {
            return "无效KeySpec"; // 无效KeySpec
        } catch (NoSuchPaddingException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (IllegalBlockSizeException e) {
            return "无效字节"; // 无效字节
        } catch (BadPaddingException e) {
            return "解析异常"; // 解析异常
        } catch (UnsupportedEncodingException e) {
            return "编码异常"; // 编码异常
        }
    }
    
    /**
     * 生成密钥key对象
     * @param key 密钥字符串
     * @return 密钥对象
     * @throws InvalidKeyException 无效的key
     * @throws NoSuchAlgorithmException 算法名称未发现
     * @throws InvalidKeySpecException 无效的KeySpec
     */
    private static Key keyGenerator(String key) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] input = hexString2Bytes(key);
        DESKeySpec desKey = new DESKeySpec(input);
        // 创建一个密钥工厂,然后用它把DESKeySpec转化
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        // 获得一个密钥
        SecretKey secretKey = keyFactory.generateSecret(desKey);
        return secretKey;
    }

    /**
     * 从十六进制字符串到字节数组转化
     * @param key 密钥
     */
    private static byte[] hexString2Bytes(String key) {
        byte[] b = new byte[key.length()/2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = key.charAt(j++);
            char c1 = key.charAt(j++);
            // c0做b[i]的高字节,c1做低字节
            b[i] = (byte) ((parse(c0)<<4)|parse(c1));
        }
        return b;
    }

    /**
     * 将字符转换为int值
     * @param c 要转化的字符
     * @return ASCII码值
     */
    private static int parse(char c) {
        if (c >= 'a') {
            return (c - 'a' + 10) & 0x0f;
        }
        if (c >= 'A') {
            return (c - 'A' + 10) & 0x0f;
        }
        return (c - '0') & 0x0f;
    }   
}

  1. 3-DES
    3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法
    示例:
/**
 * 3-DES加密工具类
 * @author mazaiting
 */
public class ThreeDESUtil {
    /**
     * 算法名称
     */
    public static final String KEY_ALGORITHM = "desede";
    /**
     * 算法名称/加密模式/填充方式
     * 
        String source = "abcdefgh"; // 无填充情况下,长度必须为8的倍数
        String key = "6C4E60E55552386C759569836DC0F83869836DC0F838C0F7";// 长度必须大于等于48
        System.out.println(key.length());
        String encryptData = ThreeDESUtil.tDesEncryptCBC(source, key);
        System.out.println("加密后: " + encryptData);
        
        String decryptData = ThreeDESUtil.tDesDecryptCBC(encryptData, key);
        System.out.println("解密后: " + decryptData);  
     */
    public static final String CIPHER_ALGORITHM = "desede/CBC/NoPadding";
    /**
     * IvParameterSpec参数
     */
    public static final byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 };
    
    /**
     * CBC加密
     * @param data 明文
     * @param key 密钥
     * @return Base64编码的密文
     */
    public static String tDesEncryptCBC(String data, String key){
        try {
            // 添加一个安全提供者
            Security.addProvider(new BouncyCastleProvider());
            // 获得密钥
            Key desKey = keyGenerator(key);
            // 获取密码实例
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec ips = new IvParameterSpec(keyiv);
            // 初始化密码
            cipher.init(Cipher.ENCRYPT_MODE, desKey, ips);
            // 执行加密
            byte[] bytes = cipher.doFinal(data.getBytes("UTF-8"));
            return Base64.encodeBase64String(bytes);
        } catch (InvalidKeyException e) {
            return "无效KEY"; // 无效KEY
        } catch (NoSuchAlgorithmException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (InvalidKeySpecException e) {
            return "无效KeySpec"; // 无效KeySpec
        } catch (NoSuchPaddingException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (IllegalBlockSizeException e) {
            return "无效字节"; // 无效字节
        } catch (BadPaddingException e) {
            return "解析异常"; // 解析异常
        } catch (UnsupportedEncodingException e) {
            return "编码异常"; // 编码异常
        } catch (InvalidAlgorithmParameterException e) {
            return "摘要参数异常"; // 摘要参数异常
        }
    }
    
    /**
     * CBC解密
     * @param data Base64编码的密文
     * @param key 密钥
     * @return
     */
    public static String tDesDecryptCBC(String data, String key) {
        try {
            Key desKey = keyGenerator(key);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec ips = new IvParameterSpec(keyiv);
            cipher.init(Cipher.DECRYPT_MODE, desKey, ips);
            byte[] bytes = cipher.doFinal(Base64.decodeBase64(data));
            return new String(bytes, "UTF-8");
        } catch (InvalidKeyException e) {
            return "无效KEY"; // 无效KEY
        } catch (NoSuchAlgorithmException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (InvalidKeySpecException e) {
            return "无效KeySpec"; // 无效KeySpec
        } catch (NoSuchPaddingException e) {
            return "无效算法名称"; // 无效算法名称
        } catch (IllegalBlockSizeException e) {
            return "无效字节"; // 无效字节
        } catch (BadPaddingException e) {
            return "解析异常"; // 解析异常
        } catch (UnsupportedEncodingException e) {
            return "编码异常"; // 编码异常
        } catch (InvalidAlgorithmParameterException e) {
            return "摘要参数异常"; // 摘要参数异常
        }
    }
    
    
    /**
     * 生成密钥key对象
     * @param key 密钥字符串
     * @return 密钥对象
     * @throws InvalidKeyException 无效的key
     * @throws NoSuchAlgorithmException 算法名称未发现
     * @throws InvalidKeySpecException 无效的KeySpec
     */
    private static Key keyGenerator(String key) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] input = hexString2Bytes(key);
        DESedeKeySpec desKey = new DESedeKeySpec(input);
        // 创建一个密钥工厂,然后用它把DESKeySpec转化
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        // 获得一个密钥
        SecretKey secretKey = keyFactory.generateSecret(desKey);
        return secretKey;
    }

    /**
     * 从十六进制字符串到字节数组转化
     * @param key 密钥
     */
    private static byte[] hexString2Bytes(String key) {
        byte[] b = new byte[key.length()/2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = key.charAt(j++);
            char c1 = key.charAt(j++);
            // c0做b[i]的高字节,c1做低字节
            b[i] = (byte) ((parse(c0)<<4)|parse(c1));
        }
        return b;
    }

    /**
     * 将字符转换为int值
     * @param c 要转化的字符
     * @return ASCII码值
     */
    private static int parse(char c) {
        if (c >= 'a') {
            return (c - 'a' + 10) & 0x0f;
        }
        if (c >= 'A') {
            return (c - 'A' + 10) & 0x0f;
        }
        return (c - '0') & 0x0f;
    }   
    
}
  1. AES加密
    AES是分组密钥,算法输入128位数据,密钥长度也是128位。

/**
 * AES加密工具类
 * @author mazaiting
 */
public class AESUtil {
    /**
     * 算法名称
     */
    public static final String KEY_ALGORITHM = "AES";
    /**
     * 算法
     * 使用:
        String source = "mazaiting";
        String key = "123456";
        
        String encryptString = AESUtil.encrypt(source, key);
        System.out.println("加密后: " + encryptString);
        
        String decryptString = AESUtil.decrypt(encryptString, key);
        System.out.println("解密后: " + decryptString);
     */
    public static final String CIPHER_ALGORITHM = "AES";
    
    
    /**
     * 加密数据
     * @param data 待加密内容
     * @param key 加密的密钥
     * @return 加密后的数据
     */
    public static String encrypt(String data, String key) {
        try {
            // 获得密钥
            Key deskey = keyGenerator(key);
            // 实例化一个密码对象
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            // 密码初始化
            cipher.init(Cipher.ENCRYPT_MODE, deskey);
            // 执行加密
            byte[] bytes = cipher.doFinal(data.getBytes("UTF-8"));
            return Base64.encodeBase64String(bytes);
        } catch (NoSuchAlgorithmException e) {
            return "加密名称异常"; // 获取加密名称异常
        } catch (UnsupportedEncodingException e) {
            return "未知编码格式"; // 未知编码格式 
        } catch (InvalidKeyException e) {
            return "无效Key"; // 无效Key
        } catch (NoSuchPaddingException e) {
            return "无效密码算法"; // 无效密码算法
        } catch (IllegalBlockSizeException e) {
            return "无效字节"; // 无效字节
        } catch (BadPaddingException e) {
            return "解析异常"; // 解析异常
        }
    }

    /**
     * 解密数据
     * @param data 待解密的内容
     * @param key 解密的密钥
     * @return
     */
    public static String decrypt(String data, String key){
        try {
            // 生成密钥
            Key kGen = keyGenerator(key);
            // 实例化密码对象
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            // 初始化密码对象
            cipher.init(Cipher.DECRYPT_MODE, kGen);
            // 执行解密
            byte[] bytes = cipher.doFinal(Base64.decodeBase64(data));
            return new String(bytes, "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            return "加密名称异常"; // 获取加密名称异常
        } catch (UnsupportedEncodingException e) {
            return "未知编码格式"; // 未知编码格式 
        } catch (InvalidKeyException e) {
            return "无效Key"; // 无效Key
        } catch (NoSuchPaddingException e) {
            return "无效密码算法"; // 无效密码算法
        } catch (IllegalBlockSizeException e) {
            return "无效字节"; // 无效字节
        } catch (BadPaddingException e) {
            return "解析异常"; // 解析异常
        }
    }
    
    /**
     * 获取密钥
     * @param key 密钥字符串
     * @return 返回一个密钥
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     */
    private static Key keyGenerator(String key) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        KeyGenerator kGen = KeyGenerator.getInstance(KEY_ALGORITHM);
        kGen.init(128, new SecureRandom(hexString2Bytes(key)));
        SecretKey secretKey = kGen.generateKey();
        byte[] encoded = secretKey.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(encoded, KEY_ALGORITHM);
        return secretKeySpec;
    }
    

    /**
     * 从十六进制字符串到字节数组转化
     * @param key 密钥
     */
    private static byte[] hexString2Bytes(String key) {
        byte[] b = new byte[key.length()/2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = key.charAt(j++);
            char c1 = key.charAt(j++);
            // c0做b[i]的高字节,c1做低字节
            b[i] = (byte) ((parse(c0)<<4)|parse(c1));
        }
        return b;
    }

    /**
     * 将字符转换为int值
     * @param c 要转化的字符
     * @return ASCII码值
     */
    private static int parse(char c) {
        if (c >= 'a') {
            return (c - 'a' + 10) & 0x0f;
        }
        if (c >= 'A') {
            return (c - 'A' + 10) & 0x0f;
        }
        return (c - '0') & 0x0f;
    }   
}

代码下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值