zoukankan      html  css  js  c++  java
  • Java实现AES ECP PKCS5Padding加解密工具类

    Java 实现一个AES/ECB/PKCS5Padding 加解密算法工具类

    • 加密算法: AES
    • 模式: ECB
    • 补码方式: PKCS5Padding

    1. 工具类

    import lombok.Getter;
    import lombok.Setter;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.util.Base64Utils;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.BufferedInputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.security.MessageDigest;
    
    /**
     * Created by @author yihui in 19:12 20/1/2.
     */
    @Slf4j
    public class EncryptUtil {
        private static final String KEY_ALGORITHM = "AES";
        /**
         * 算法/模式/补码方式
         */
        private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
        private static final String CODE = "utf-8";
    
        @Setter
        @Getter
        public static String encryptKey;
    
        public static String encrypt(String content) {
            return encrypt(content, encryptKey);
        }
    
        /**
         * 加密
         *
         * @param content
         * @param key
         * @return
         * @throws Exception
         */
        public static String encrypt(String content, String key) {
            try {
                byte[] encrypted = encrypt2bytes(content, key);
                return Base64Utils.encodeToString(encrypted);
            } catch (Exception e) {
                log.error("failed to encrypt: {} of {}", content, e);
                return null;
            }
        }
    
        public static byte[] encrypt2bytes(String content, String key) {
            try {
                byte[] raw = key.getBytes(CODE);
                SecretKeySpec secretKeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
                Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
                return cipher.doFinal(content.getBytes(CODE));
            } catch (Exception e) {
                log.error("failed to encrypt: {} of {}", content, e);
                return null;
            }
        }
    
        public static String decrypt(String content) {
            try {
                return decrypt(content, encryptKey);
            } catch (Exception e) {
                log.error("failed to decrypt: {}, e: {}", content, e);
                return null;
            }
        }
    
        /**
         * 解密
         *
         * @param content
         * @param key
         * @return
         * @throws Exception
         */
        public static String decrypt(String content, String key) throws Exception {
            return decrypt(Base64Utils.decodeFromString(content), key);
        }
    
        public static String decrypt(byte[] content, String key) throws Exception {
            if (key == null) {
                log.error("AES key should not be null");
                return null;
            }
    
            byte[] raw = key.getBytes(CODE);
            SecretKeySpec keySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            try {
                byte[] original = cipher.doFinal(content);
                return new String(original, CqODE);
            } catch (Exception e) {
                log.error("failed to decrypt content: {}/ key: {}, e: {}", content, key, e);
                return null;
            }
        }
    }
    

    请注意上面的实现,提供了两种方式

    • 一个是AES加密之后使用base64编码输出,对应的是解密base64编码的数据
    • 一个是AES加密之后,直接返回字节数组;也是直接解码字节数组

    2. 测试case

    我们提供了两个加密的文件,用于解密使用;

    base64加解密

    @Test
    public void testEncrypt() throws Exception {
        String abc = "Hello, 一灰灰Blog!";
        String key = "JC66fRd3wj85k8Hr";
        String out = EncryptUtil.encrypt(abc, key);
        System.out.println(out);
    
        System.out.println(EncryptUtil.decrypt(out, key));
    }
    

    输出结果如:

    TKrN7VKrqsAQ4JqygeHOlG21Sd3IRJ3Y11k4kOdOG4s=
    Hello, 一灰灰Blog!
    

    字节数组加解密

    @Test
    public void testEncryptByte() throws Exception {
        String abc = "Hello, 一灰灰Blog!";
        String key = "JC66fRd3wj85k8Hr";
        byte[] out = EncryptUtil.encrypt2bytes(abc, key);
        System.out.println(new String(out));
    
        System.out.println(EncryptUtil.decrypt(out, key));
    }
    

    输出结果如:

    // 加密的字节数组,就是乱码... 你没看错
    L���R��������Δm�I��D���Y8��N�
    Hello, 一灰灰Blog!
    

    为什么有上面两种区别?

    如果我们将加密后的字节数组,直接 new String() 获得一个字符串,然后解密这个字符串,会发现解密失败哦

    简单修改一下上面的测试用例

    @Test
    public void testEncryptByte() throws Exception {
        String abc = "Hello, 一灰灰Blog!";
        String key = "JC66fRd3wj85k8Hr";
        byte[] out = EncryptUtil.encrypt2bytes(abc, key);
        String enc = new String(out, "utf-8");
        System.out.println(enc);
    
        System.out.println(EncryptUtil.decrypt(enc.getBytes("utf-8"), key));
    }
    

    执行之后,发现解密失败

    为啥会出现这样情况呢?

    • enc = new String(out, "utf-8")enc.getBytes("utf-8") 字节数组转字符串; 字符串转字节数组这两个过程会导致最终生成的字节数组,与原始的不一致!!!

    解密远程资源的case

    最后给一个解密远程加密的二进制文件的实例case

    private void binKey(String uri, String key) throws Exception {
        // 这个文件是没有base64编码,直接上传的二进制
        URL url = new URL(uri);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        InputStream stream = connection.getInputStream();
        int lenth = connection.getContentLength();
        byte[] out = new byte[lenth];
        stream.read(out);
        stream.close();
        String ans = decrypt(out, key);
        System.out.println(ans);
    }
    
    public void testDe() throws Exception {
        String key = "5JRHMJn8xHnMDRXa";
        binKey("http://q8rnsprw0.bkt.clouddn.com/mwzz/b0001", key);
    }
    

    II. 其他

    1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

    一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

    2. 声明

    尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

    3. 扫描关注

    一灰灰blog

    QrCode

  • 相关阅读:
    胖子哥的大数据之路(12)-三张图告诉你大数据安全方案设计
    Building the Unstructured Data Warehouse: Architecture, Analysis, and Design
    Hadoop专业解决方案-第3章:MapReduce处理数据
    胖子哥的大数据之路(11)-我看Intel&&Cloudera的合作
    胖子哥的大数据之路(10)- 基于Hive构建数据仓库实例
    胖子哥的大数据之路(9)-数据仓库金融行业数据逻辑模型FS-LDM
    胖子哥的大数据之路(8)- 数据仓库命名规范
    胖子哥的大数据之路(7)- 传统企业切入核心or外围
    dos 打开计算机管理
    C# SQLite数据库
  • 原文地址:https://www.cnblogs.com/yihuihui/p/12812472.html
Copyright © 2011-2022 走看看