Java 实现一个 AES/ECB/PKCS5Padding
加解密算法工具类
<!-- more -->
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; } } }
请注意上面的实现,提供了两种方式
我们提供了两个加密的文件,用于解密使用;
@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
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); }
一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激