您好,我已经加密了十六进制字符串和使用标准 AES 算法加密的密钥。
代码:
final String key = "=abcd!#Axd*G!pxP";
final javax.crypto.spec.SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
final javax.crypto.Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte [] encryptedValue = cipher.doFinal(input.getBytes());
return new String(org.apache.commons.codec.binary.Hex.encodeHex(encryptedValue));
现在我尝试使用 C# 解密它
代码:
RijndaelManaged rijndaelCipher = new RijndaelManaged();
// Assumed Mode and padding values.
rijndaelCipher.Mode = CipherMode.ECB;
rijndaelCipher.Padding = PaddingMode.None;
// AssumedKeySize and BlockSize values.
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
// Convert Hex keys to byte Array.
byte[] encryptedData = hexStringToByteArray(textToDecrypt);
byte[] pwdBytes = Encoding.Unicode.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
// Decrypt data
byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
str = Encoding.UTF8.GetString(plainText);
and
static private byte[] HexToBytes(string str)
{
if (str.Length == 0 || str.Length % 2 != 0)
return new byte[0];
byte[] buffer = new byte[str.Length / 2];
char c;
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
{
// Convert first half of byte
c = str[sx];
buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);
// Convert second half of byte
c = str[++sx];
buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
}
return buffer;
}
但输出并不如预期。
请指出我哪里错了?
您的代码有一个大问题:它混合了字符编码!
在Java中你正在调用key.getBytes()
,无参数。此方法返回 UTF-8 或 CP1252/ISO 8859-1 编码数据,具体取决于您的操作系统和 Java 中的默认字符集。
在 C# 端,您正在使用Encoding.Unicode.GetBytes(key)
- .Net 中的“Unicode”是双字节字符别名 UTF-16 (Little-Endian) 的同义词 http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx。因此,您在 C# 中使用不同的键。
通过比较 Java 和 C# 中的字节数,您应该能够看到差异:
Java: "=abcd!#Axd*G!pxP".getBytes().length = 16
C#: Encoding.Unicode.GetBytes("=abcd!#Axd*G!pxP").Length = 32
我强烈建议您使用字节数组而不是字符串来定义加密密钥。
更新:另一个区别是您在 C# 中设置了初始化向量 (IV),而在 Java 中则没有这样做。当您使用 ECB 时,不应使用 IV,但如果您更改为 CBC,则会产生很大的差异。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)