我正在尝试解密一些东西,该东西使用.NET/C#的RijndaelManaged进行了加密,并使用Java进行解密。
C#程序不是我的,我无法更改它以实现更好的互操作性。但我知道它是如何加密的:
byte[] bytes = new UnicodeEncoding().GetBytes(password); // edit: built-in is 8chars
FileStream fileStream = new FileStream(outputFile, FileMode.Create);
RijndaelManaged rijndaelManaged = new RijndaelManaged();
CryptoStream cryptoStream = new CryptoStream((Stream) fileStream,
rijndaelManaged.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write);
我不知道如何在Java端解密这个内容。我找到了这篇博客文章,但它缺乏实际细节,我无法实现解密器。
编辑:我是个傻瓜,现在它可以工作了。
Unicode编码 是UTF-16LE,而我使用的是UTF-8。在插入密码时切换到正确的编码已经修复了程序。
我还需要获取BouncyCastle并执行Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
最终编辑:以下是在Java中解密默认.NET RijndaelManaged流的代码,假设它是使用原始密码作为密钥创建的:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
String password = "kallisti"; // only 8, 12, or 16 chars will work as a key
byte[] key = password.getBytes(Charset.forName("UTF-16LE"));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"),
new IvParameterSpec(key));
return cipher; // then use CipherInputStream(InputStream, Cipher)
请记住:如果您控制C#端,请不要使用未派生的密码作为密钥!
new UnicodeEncoding().GetBytes(password);
来获取密码的字节。原因请参考 http://en.wikipedia.org/wiki/PBKDF2 和 http://tools.ietf.org/html/rfc2898,尤其是第3节。幸运的是,.NET和Java都有符合RFC2898标准(又名PKCS5,又名PBKDF2)的密钥派生类。你的应用程序应该使用它们。 - Cheeso