在项目中遇到这么一个问题:
java端需要把一些数据AES加密后传给C#端,找了好多资料,算是解决了,分享一下:
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.SecureRandom; public class AesEncodeUtil { private final static String transferKey ="qazwsxedcrfv12345"; public static void main(String[] args) throws Exception { String a = aesTransferEncrypt("QAZwsx123!@#$%^&*");
System.out.println(a);
System.out.println(aesTransferDncrypt(a)); } /**
* 传输用加密
* @param content
* @return
* @throws Exception
*/
public static String aesTransferEncrypt(String content) throws Exception {
return base64Encode(aesEncryptToBytes(content, transferKey));
} /**
* 传输用解密
* @param content
* @return
* @throws Exception
*/
public static String aesTransferDncrypt(String encryptStr) throws Exception {
return aesDecryptByBytes(base64Decode(encryptStr), transferKey);
} /**
* base 64 encode
* @param bytes 待编码的byte[]
* @return 编码后的base 64 code
*/
private static String base64Encode(byte[] bytes) {
return new BASE64Encoder().encode(bytes);
} /**
* base 64 decode
* @param base64Code 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception
*/
private static byte[] base64Decode(String base64Code) throws Exception {
return new BASE64Decoder().decodeBuffer(base64Code);
} /**
* AES加密
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的byte[]
* @throws Exception
*/
private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
secureRandom.setSeed(encryptKey.getBytes());
kgen.init(, secureRandom);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, kgen.generateKey());
return cipher.doFinal(content.getBytes("UTF-8"));
} /**
* AES解密
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
* @throws Exception
*/
private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
secureRandom.setSeed(decryptKey.getBytes());
kgen.init(, secureRandom);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE,kgen.generateKey());
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes,"UTF-8");
}
}
java代码加密/解密运行结果:
加密结果:BKscOr7eK4jTO5Hcw5oxqS8HWg2SRhtGfMctz8t/45g=
解密结果:QAZwsx123!@#$%^&*
再看看C#代码:
/// <summary>
/// AES加密 (128-ECB加密模式)
/// </summary>
/// <param name="toEncrypt">内容</param>
/// <param name="key">秘钥</param>
/// <returns></returns>
public static string AESEncrypt(string toEncrypt, string key)
{
byte[] keyArray = Convert.FromBase64String(key);
byte[] toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt); RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, , toEncryptArray.Length); return Convert.ToBase64String(resultArray, , resultArray.Length);
}
/// <summary>
/// AES解密(128-ECB加密模式)
/// </summary>
/// <param name="toDecrypt">密文</param>
/// <param name="key">秘钥(Base64String)</param>
/// <returns></returns>
public static string AESDecrypt(string toDecrypt, string key)
{
try
{
byte[] keyArray = Convert.FromBase64String(key); //128bit
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray; //获取或设置对称算法的密钥
rDel.Mode = CipherMode.ECB; //获取或设置对称算法的运算模式,必须设置为ECB
rDel.Padding = PaddingMode.PKCS7; //获取或设置对称算法中使用的填充模式,必须设置为PKCS7
ICryptoTransform cTransform = rDel.CreateDecryptor(); //用当前的 Key 属性和初始化向量 (IV) 创建对称解密器对象
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, , toEncryptArray.Length);
return Encoding.UTF8.GetString(resultArray);
}
catch
{
return null;
}
}
但是如果直接把 transferKey ="qazwsxedcrfv12345" 和 加密结果:BKscOr7eK4jTO5Hcw5oxqS8HWg2SRhtGfMctz8t/45g=
给C#,C#是无法解密的,因为 rDel.Key = keyArray; 会报错。
那么怎么办呢? 其实我们要把transferKey ="qazwsxedcrfv12345" 处理下,
import java.security.NoSuchAlgorithmException;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import sun.misc.BASE64Encoder;
public class t1 {
public static void main(String[] args) throws NoSuchAlgorithmException {
String transferKey ="bt龘靐麷鸜郁nm018讟虋纞idnwtyaTN滟厵麷鸜郁骊NkkdTnd11_!@$齽齼鼺黸TTASdg212c驫饢籱21_djTdj";
KeyGenerator kgen = KeyGenerator.getInstance("AES");
java.security.SecureRandom random = java.security.SecureRandom.getInstance("SHA1PRNG");
random.setSeed(transferKey.getBytes());
kgen.init(128, random);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
BASE64Encoder coder = new BASE64Encoder();
System.out.println(coder.encode(enCodeFormat));
}
}
运行结果:0UkIZmHsXb0BUql/L3R6Aw== 才是C#需要的key
看看C#调用及结果:
以上只是一个简单的示例。