加密代码
/** * 解密 * * @param content 待解密内容 * @param password 解密密钥 * @return */ public static byte[] decrypt(byte[] content, String password) { try { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128, new SecureRandom(password.getBytes())); SecretKey secretKey = kgen.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES"); // 创建密码器 cipher.init(Cipher.DECRYPT_MODE, key); // 初始化 byte[] result = cipher.doFinal(content); return result; // 加密 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; }
解密代码
/** * 解密 * * @param content 待解密内容 * @param password 解密密钥 * @return */ public static byte[] decrypt(byte[] content, String password) { try { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128, new SecureRandom(password.getBytes())); SecretKey secretKey = kgen.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES");// 创建密码器 cipher.init(Cipher.DECRYPT_MODE, key); // 初始化 byte[] result = cipher.doFinal(content); return result; // 加密 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; }
解密demo
String content = "test"; String password = "12345678"; // 加密 System.out.println("加密前:" + content); byte[] encryptResult = encrypt(content, password); try { String encryptResultStr = new String(encryptResult,"utf-8"); // 解密 byte[] decryptResult = decrypt(encryptResultStr.getBytes("utf-8"),password); System.out.println("解密后:" + new String(decryptResult)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
偶尔会报错、抛出异常:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
问题原因:
加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;
要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示
解决方案
二进制转换成16进制
/** * 将二进制转换成16进制 * * @param buf 二进制字节数组 * @return 16进制字符串 */ private static String parseByte2HexStr(byte[] buf) { StringBuilder sb = new StringBuilder(); for (byte _byte : buf) { String hex = Integer.toHexString(_byte & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); }
16进制转换为二进制
/** * 将16进制转换为二进制 * * @param hexStr 16进制字符串 * @return 二进制字节数组 */ private static byte[] parseHexStr2Byte(String hexStr) { if (hexStr.length() < 1) { throw new NullPointerException("the param hexStr(String) is blank"); } byte[] result = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / 2; i++) { int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); result[i] = (byte) (high * 16 + low); } return result; }
测试结果,问题解决:
String content = "test"; String password = "12345678"; // 加密 System.out.println("加密前:" + content); byte[] encryptResult = encrypt(content, password); String encryptResultStr = parseByte2HexStr(encryptResult); System.out.println("加密后:" + encryptResultStr); // 解密 byte[] decryptFrom = parseHexStr2Byte(encryptResultStr); byte[] decryptResult = decrypt(decryptFrom,password); System.out.println("解密后:" + new String(decryptResult));