公司最近做agent项目,需要对一些远程重要的请求参数进行加密。加密之前选型,选择了AES,而DES算法加密,容易被破解。网上有很多关于加密的算法的Demo案列,我发现这些Demo在Window平台运行正常,然后再MAC下就一直报错,现在选择网上常见的AES加密算法如下:

一·AES加密

 /**
* AES加密字符串
*
* @param content
* 需要被加密的字符串
* @param password
* 加密需要的密码
* @return 密文
*/
public static byte[] encrypt(String content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者 kgen.init(128, new SecureRandom(password.getBytes()));// 利用用户密码作为随机数初始化出
// 128位的key生产者
//加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行 SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥 byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回
// null。 SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥 Cipher cipher = Cipher.getInstance("AES");// 创建密码器 byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器 byte[] result = cipher.doFinal(byteContent);// 加密 return result; } catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}

二.AES解密

  /**
* 解密AES加密过的字符串
*
* @param content
* AES加密过过的内容
* @param password
* 加密时的密码
* @return 明文
*/
public static byte[] decrypt(byte[] content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
kgen.init(128, new SecureRandom(password.getBytes()));
SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为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;
}

三.测试

  public static void main(String[] args) {
String content = "对面的楼上的男生,你们有女朋友吗?";
String password = "123456789";
System.out.println("加密之前:" + content); // 加密
byte[] encrypt = AesTest.encrypt(content, password);
System.out.println("加密后的内容:" + new String(encrypt)); // 解密
byte[] decrypt = AesTest.decrypt(encrypt, password);
System.out.println("解密后的内容:" + new String(decrypt));
}

以上代码在Window平台上运行正常,但是在MAC下运行加密正常,解密一直以下报 Given final block not properly padded的错!!!

网上查了很多资料,最后分析了下错误原因:

SecureRandom 实现完全随操作系统本身的内部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 MAC 或部分 linux 系统上则不同。两次加密,解密产生的密钥都不相同,所以解密就报错。为了规避这个错误,采用了另一种AES加密的方法,而且需要添加2个依赖jar包。两个依赖的maven坐标是:

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.apache.directory.studio</groupId>
<artifactId>org.apache.commons.codec</artifactId>
<version>1.8</version>
</dependency>

下面是改进后的代码:

 package com.corearchi.utils;

 import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils; import sun.misc.BASE64Decoder; /**
* AES算法进行加密
*
* @author CodeGeek
* @create 2018-01-23 上午11:00
**/
public class EncryptUtils { /**
* 密钥
*/
private static final String KEY = "1234567887654321";// AES加密要求key必须要128个比特位(这里需要长度为16,否则会报错) /**
* 算法
*/
private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding"; public static void main(String[] args) throws Exception {
String content = "url:findNames.action";
System.out.println("加密前:" + content); System.out.println("加密密钥和解密密钥:" + KEY); String encrypt = aesEncrypt(content, KEY);
System.out.println("加密后:" + encrypt); String decrypt = aesDecrypt(encrypt, KEY); System.out.println("解密后:" + decrypt);
} /**
* base 64 encode
* @param bytes 待编码的byte[]
* @return 编码后的base 64 code
*/
private static String base64Encode(byte[] bytes){
return Base64.encodeBase64String(bytes);
} /**
* base 64 decode
* @param base64Code 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception 抛出异常
*/
private static byte[] base64Decode(String base64Code) throws Exception{
return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
} /**
* AES加密
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的byte[]
*/
private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES")); return cipher.doFinal(content.getBytes("utf-8"));
} /**
* AES加密为base 64 code
*
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的base 64 code
*/
private static String aesEncrypt(String content, String encryptKey) throws Exception {
return base64Encode(aesEncryptToBytes(content, encryptKey));
} /**
* AES解密
*
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
*/
private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
byte[] decryptBytes = cipher.doFinal(encryptBytes); return new String(decryptBytes);
} /**
* 将base 64 code AES解密
*
* @param encryptStr 待解密的base 64 code
* @param decryptKey 解密密钥
* @return 解密后的string
*/
private static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
} }

这个时候在MAC下就可以正常运行了,在Window以及Linux上都可以正常运行。

使用java实现AES加密的更多相关文章

  1. java使用AES加密解密 AES-128-ECB加密

    java使用AES加密解密 AES-128-ECB加密 import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; impo ...

  2. Java实现AES加密,异常java.security.InvalidKeyException: Illegal key size 的解决

    Java实现AES加密,抛出异常如下:java.security.InvalidKeyException: Illegal key size 代码参考 http://my.oschina.net/Ja ...

  3. Java实现AES加密(window机器和linux机器) 注意window机器 和linux机器算法稍有不同

    一)什么是AES? 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用. ...

  4. [Java 实现AES加密解密]

    今天同学请教我这个问题,被坑了次…… 实现的功能是2个Java类:一个读取源文件生成加密文件,另一个类读取加密文件来解密. 整个过程其实很简单,java有AES的工具包,设好秘钥,设好输入内容,就得到 ...

  5. Java实现AES加密

    一)什么是AES? 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用. ...

  6. php与java通用AES加密解密算法

    AES指高级加密标准(Advanced Encryption Standard),是当前最流行的一种密码算法,在web应用开发,特别是对外提供接口时经常会用到,下面是我整理的一套php与java通用的 ...

  7. 使用java进行 AES 加密 解密?

    百度百科是这样定义的: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标 ...

  8. Java使用AES加密解密

    AES加密机制: 密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准. 这个标准用来替代原先的 ...

  9. 【java】AES加密解密|及Base64的使用

    转载自:http://www.cnblogs.com/arix04/archive/2009/10/15/1511839.html AES加解密算法,使用Base64做转码以及辅助加密: packag ...

  10. mysql java 通用AES加密

    最近有个需求,需要对数据库某些字段加密,调研发现采用AES加密的方式较多,而且反向解密速度快,符合需求,于是采用:下面是遇到的问题及相关代码 首先第一个问题,AES的秘钥是16位,mysql的密码长度 ...

随机推荐

  1. Linux下安装方法总结(源码安装)

    很久之前安装过windows下以及Mac下的node,感觉还是很方便的,不成想今天安装Linux下的坑了老半天,特此记录. 首先去官网下载代码,这里一定要注意安装分两种,一种是Source Code源 ...

  2. 在自己机器上实现apache的多域名

    自己机器上有3个目录,分别是/var/www/html/                             /var/www/solaris/                           ...

  3. hdu-1395 2^x mod n = 1---求阶(欧拉函数)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1395 题目大意: 题目中给出输入一个整数n,要求一个最小整数的x,使得2^x mod n=1; 解题 ...

  4. AsyncTask使用实例,异步加载图片

    在上一篇,详细介绍了AsynTask的基础知识.没有读过的朋友可以点击下面的链接: http://www.cnblogs.com/fuly550871915/p/4892310.html 那么在这篇文 ...

  5. SQL表创建注意事项

    CREATE TABLE V_USER ( AUTOID ), USERID BYTE) NOT NULL, USERNAME BYTE) NOT NULL, USERPASSWORD BYTE) N ...

  6. UVA10820 Send a Table

    嘟嘟嘟 [欧拉函数] 大致题意:如果知道f(a, b),就可以求出f(a * k, b * k).现给出一个n,求至少需要知道几个二元组(a, b),使所有的f(x, y)都能求出来.(1 <= ...

  7. 配置开发环境&安装sklearn

    我的开发环境是Jupyter lab,所用的库和版本大家参考: Python 3.7.1(你的版本至少要3.4以上) Scikit-learn 0.20.0 (你的版本至少要0.19) Graphvi ...

  8. Anaconda安装与常用命令及方法(深度学习入门1)

    Anaconda是一个软件发行版,它附带了 conda.Python 和 150 多个科学包及其依赖项. 安装Anaconda Anaconda分为Linux.Windows.Mac等版本,去 htt ...

  9. 使用Scanner将InputStream类型转换成String

    我们在测试项目中经常会遇到这样的情形: 1. 从文件或网络得到一个InputStream,需要转换成String赋值到别的变量做为另一个方法的入参. 2. 从文件或网络得到一个InputStream后 ...

  10. HIDU 2094

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=2094 产生冠军 Time Limit: 1000/1000 MS (Java/Others)    M ...