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

简介: Java 实现一个AES/ECB/PKCS5Padding 加解密算法工具类加密算法: AES模式: ECB补码方式: 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));
}
复制代码


执行之后,发现解密失败

image.png


为啥会出现这样情况呢?

  • 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);
}



相关文章
|
人工智能 JSON Java
列表结构与树结构转换分析与工具类封装(java版)
本文介绍了将线性列表转换为树形结构的实现方法及工具类封装。核心思路是先获取所有根节点,将其余节点作为子节点,通过递归构建每个根节点的子节点。关键在于节点需包含 `id`、`parentId` 和 `children` 三个属性。文中提供了两种封装方式:一是基于基类 `BaseTree` 的通用工具类,二是使用函数式接口实现更灵活的方式。推荐使用后者,因其避免了继承限制,更具扩展性。代码示例中使用了 Jackson 库进行 JSON 格式化输出,便于结果展示。最后总结指出,理解原理是进一步优化和封装的基础。
416 0
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
1100 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
Java
Java 些许公共工具类
Java 些许公共工具类
127 1
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
303 8
|
算法 Java 数据安全/隐私保护
最新版-Python和Java实现Aes相互加解密
最新版-Python和Java实现Aes相互加解密
659 0
|
算法 安全 数据安全/隐私保护
Java-AES加解密
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。高级加密标准算法从很多方面解决了令人担忧的问题。实际上,攻击数据加密标准的那些手段对于高级加密标准算法本身并没有效果。如果采用真正的128位加密技术甚至256位加密技术,蛮力攻击要取得成功需要耗费相当长的时间。安全研究人员还没有那么多的时间对这种加密方法进行破解试验。我们可能会随时发现一种全新的攻击手段会攻破这种高级加密标准。至少在理论上存在这种可能性。
577 0
|
存储 算法 Java
Java使用AES加解密
Java使用AES加解密 目录 1.1生成密钥 1.2密钥的存储 1.3获取存储的密钥 1.4加解密 1.5使用存储的密钥进行加解密示例   AES是一种对称的加密算法,可基于相同的密钥进行加密和解密。
5570 1
|
6月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
332 1
|
6月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
332 1
下一篇
开通oss服务