前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java实现AES ECP PKCS5Padding加解密工具类

Java实现AES ECP PKCS5Padding加解密工具类

作者头像
一灰灰blog
发布2020-05-09 16:36:16
1.3K0
发布2020-05-09 16:36:16
举报
文章被收录于专栏:小灰灰小灰灰

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

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

<!-- more -->

1. 工具类

代码语言:javascript
复制
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加解密

代码语言:javascript
复制
@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));
}

输出结果如:

代码语言:javascript
复制
TKrN7VKrqsAQ4JqygeHOlG21Sd3IRJ3Y11k4kOdOG4s=
Hello, 一灰灰Blog!

字节数组加解密

代码语言:javascript
复制
@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));
}

输出结果如:

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

为什么有上面两种区别?

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

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

代码语言:javascript
复制
@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

代码语言:javascript
复制
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);
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 工具类
  • 2. 测试case
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档