我已经编写了两个函数来解密和加密C#和Javascript中的消息,但我也需要它用Java,我不能像以前那样工作。
JS加密方法:
this.aesEncrypt = function (encryptedMessage) {
var key = CryptoJS.enc.Utf8.parse("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var initialVector = CryptoJS.enc.Utf8.parse("xxxxxxxxxxxxxxxx");
var encryptedText = CryptoJS.AES.encrypt(encryptedMessage, key,
{
iv: initialVector,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encryptedText.toString().hexEncode();
}
String.prototype.hexEncode = function () {
var hex, i;
var result = "";
for (i = 0; i < this.length; i++) {
hex = this.charCodeAt(i).toString(16);
result += ("0" + hex).slice(-2);
}
return result;
}
C#解密方法:
private static string AesDecrypt(string encryptedMessage)
{
try
{
var temp = FromHex(encryptedMessage);
var encryptedBytes = Convert.FromBase64String(Encoding.ASCII.GetString(temp));
var aes = new AesCryptoServiceProvider
{
BlockSize = 128,
KeySize = 256,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
Key = Encoding.UTF8.GetBytes("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
IV = Encoding.UTF8.GetBytes("xxxxxxxxxxxxxxxx")
};
var crypto = aes.CreateDecryptor(aes.Key, aes.IV);
var secret = crypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
crypto.Dispose();
return Encoding.ASCII.GetString(secret);
}
catch (Exception)
{
return null;
}
}
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
var raw = new byte[hex.Length / 2];
for (var i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
Java加密方法:
public static String toHex(String arg) {
return String.format("%x", new BigInteger(1, arg.getBytes()));
}
public static String AesEncrypt(String encryptedMessage){
try {
IvParameterSpec initialVector = new IvParameterSpec("xxxxxxxxxxxxxxxx".getBytes("UTF-8"));
SecretKeySpec secretKeySpec = new SecretKeySpec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initialVector);
byte[] encrypted = cipher.doFinal(encryptedMessage.getBytes());
StringBuilder encryptedSb = new StringBuilder(encrypted.length);
for (byte i : encrypted){
encryptedSb.append(i);
}
return toHex(encryptedSb.toString());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
Java在加密后返回80个六位数,JS返回48个六位数。 AFAIK Java PKCS5填充与C#PKCS7填充相同。
我也尝试使用
使用结果的base64编码
http://commons.apache.org/proper/commons-codec/download_codec.cgi
,但它仍然没有。
public static String AesEncrypt(String encryptedMessage){
try {
IvParameterSpec initialVector = new IvParameterSpec("xxxxxxxxxxxxxxxx".getBytes("UTF-8"));
SecretKeySpec secretKeySpec = new SecretKeySpec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initialVector);
byte[] encrypted = cipher.doFinal(encryptedMessage.getBytes());
byte[] base64 = Base64.encodeBase64(encrypted);
StringBuilder encryptedSb = new StringBuilder(base64.length);
for (byte i : base64){
encryptedSb.append(i);
}
return toHex(encryptedSb.toString());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
答案 0 :(得分:2)
无论其他参数如何,AES都以16字节块运行。 Java AES中的PCKS#5填充将解析为PCKS#7。使用PCKS#7,您将填充到块边界;即填充最近的16个字节。
你的UTF-8输入“ABC”是3个字节。 16个字节将需要(16-3)= 13 字节的填充。因此,密文将是16个字节,或32个十六进制字符。
总而言之,我相信您的StringBuilder
和toHex()
逻辑之间的编码转换有问题。尝试使用DatatypeConverter.printHexBinary(byte[] val)
将byte[] encrypted
转换回十六进制。
答案 1 :(得分:-1)
我忘记了编码到Base64。我在最近的问题编辑中几乎就在那里。我只是忘记了Base64.encodeBase64String
哪些实际上没有用,但我看了Base64
类中这个函数的实现,我发现如何更明确地实现它。
public static String AesEncrypt(String encryptedMessage){
try {
IvParameterSpec initialVector = new IvParameterSpec("xxxxxxxxxxxxxxxx".getBytes("UTF-8"));
SecretKeySpec secretKeySpec = new SecretKeySpec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initialVector);
byte[] encrypted = cipher.doFinal(encryptedMessage.getBytes());
String base64 = StringUtils.newStringUtf8(Base64.encodeBase64(encrypted, false));
return toHex(base64);
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}