问题描述
您好,我已经加密了使用标准 AES 算法加密的十六进制字符串和密钥.代码:
Hello I've Encrypted Hex string and Key that has been encrypted using standard AES Algorithm.Code:
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# 解密它代码:
Now I try to decrypt it using C#Code:
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);
和
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;
}
但输出不符合预期.请指出我哪里出错了?
but the output is not as expected.Please point out where I'm going wrong?
推荐答案
你的代码有一个大问题:它混合了字符编码!
Your code has one big problem: It is mixing the character encodings!
在 Java 中,您调用 key.getBytes()
,不带参数.此方法返回 UTF-8 或 CP1252/ISO 8859-1 编码数据,具体取决于您的操作系统和 Java 中的默认字符集.
In Java you are calling key.getBytes()
, without arguments. This method returns the UTF-8 or CP1252/ISO 8859-1 encoded data depending on your operating system and the default charset in Java.
在 C# 方面,您使用 Encoding.Unicode.GetBytes(key)
- "Unicode" in .Net 是双字节字符别名 UTF-16 (Little-Endian) 的同义词.因此,您在 C# 中使用了不同的键.
On C# side you are using Encoding.Unicode.GetBytes(key)
- "Unicode" in .Net is a synonym for double byte characters alias UTF-16 (Little-Endian). Therefore you are using a different key in C#.
通过比较 Java 和 C# 中的字节数,您应该能够看到差异:
You should be able to see the difference by comparing the number of bytes in Java and C#:
Java:"=abcd!#Axd*G!pxP".getBytes().length = 16
C#: Encoding.Unicode.GetBytes("=abcd!#Axd*G!pxP").Length = 32
我强烈建议您使用字节数组而不是字符串来定义加密密钥.
I strongly recommend you to use byte arrays instead of Strings for defining a cryptographic key.
更新:另一个区别是您在 C# 中设置了一个初始化向量 (IV),而在 Java 中则没有.当您使用 ECB 时,不应使用 IV,但如果您更改为 CBC,例如这会产生很大的不同.
Update: Another difference is that you are setting an initialization vector (IV) in C# which you don't do in Java. As you are using ECB the IV should not be used but if you change to CBC for example this makes a big difference.
这篇关于Java 中的 AES 加密和 C# 中的解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!