1.情景展示
Java提供的密钥,C#无法解密。
2.原因分析
在Java中,AES的实际密钥需要用到KeyGenerator 和 SecureRandom,但是C#和.NET 里面没有这2个类,
所以,无法使用安全随机数生成KEY,进而导致解密失败。
Java对密钥做的进一步处理:
参数说明:
加密模式:ECB(默认值)、CBC
填充模式:PKCS5Padding(java只有这一种,其它语言使用PKCS7Padding即可,5和7没有区别)
数据块:128位(java只有这一种)
3.解决方案
超级简单的方法见最后(20190921)
方案一:推荐使用
思路:
将由Java生成的AES所需要的实际密钥,提供给C#,然后C#用这个实际的key去解密。
由于C#中byte范围是[0,255],而Java中的byte范围是[-128,127],所以,我们需要对生成的二进制密钥进行处理。
因此,Java作为密钥的提供方,需要将二进制转成16进制,C#将接收到的16进制密钥转换成二进制即可。
流程图:
java AES 加密
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.log4j.Logger;
/**
* AES加密算法工具类
* @explain 可逆算法:加密、解密
* AES/ECB/PKCS5Padding
* @author Marydon
* @creationTime 2018年7月7日下午2:17:43
* @version 3.0
* @since 2.0
* @email marydon20170307@163.com
*/
public class AESUtils {
private static Logger log = Logger.getLogger(AESUtils.class);
// 定义字符集
private static final String ENCODING = "UTF-8";
/**
* 根据提供的密钥生成AES专用密钥
* @explain
* @param password
* 可以是中文、英文、16进制字符串
* @return AES密钥
* @throws Exception
*/
public static byte[] generateKey(String password) throws Exception {
byte[] keyByteArray = null;
// 创建AES的Key生产者
KeyGenerator kgen = KeyGenerator.getInstance("AES");
// 利用用户密码作为随机数初始化
// 指定强随机数的生成方式
// 兼容linux
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(password.getBytes(ENCODING));
kgen.init(128, random);// 只能是128位
// 根据用户密码,生成一个密钥
SecretKey secretKey = kgen.generateKey();
// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回null。
keyByteArray = secretKey.getEncoded();
return keyByteArray;
}
/**
* AES加密字符串
* @param content
* 需要被加密的字符串
* @param password
* 加密需要的密码
* @return 16进制的密文(密文的长度随着待加密字符串的长度