我想使用Java和.Net进行AES 256加密/解密。这意味着我应该能够使用Java进行加密,并能够使用.Net和Vice vesra进行解密。以下是Java AES 256加密。
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(KEY.toCharArray(), SALT.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
System.out.println(Cipher.getMaxAllowedKeyLength("AES"));
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
return new String(Base64.encodeBase64(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))));
最佳答案
1)Java解密部分由
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(KEY.toCharArray(), SALT.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
return new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt.getBytes("UTF-8"))));
其中,
strToDecrypt
是Base64编码的加密数据(由加密部分的返回值提供),并且仅在最后两行中偏离加密部分。注意:实际上,IV应该是随机生成的(例如Generating random IV for AES in Java)。但是我认为这很清楚,0序列仅用于测试目的。
2)关于密钥派生
PBKDF2WithHmacSHA256
,C#解决方案取决于您的.NET-framework版本。对于V4.7.2及更高版本,可以使用以下方法派生密钥:// .NET Framework 4.7.2 +
byte[] secretKey = null;
using (Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(KEY, Encoding.UTF8.GetBytes(SALT), 65536, HashAlgorithmName.SHA256))
{
secretKey = rfc2898.GetBytes(32);
}
注意:
Rfc2898DeriveBytes
的先前实现(v4.7.2之前)使用SHA1
(硬编码)代替SHA256
,因此,没有ctor期望有4个参数。此外,Rfc2898DeriveBytes
类要求盐长度至少为8个字节,否则抛出System.ArgumentException: Salt is not at least eight bytes
。替代方法是:
// .NET Framework 4.5 +
byte[] secretKey = null;
KeyDerivationPrf keyDerivationPrf = KeyDerivationPrf.HMACSHA256;
secretKey = KeyDerivation.Pbkdf2(KEY, Encoding.UTF8.GetBytes(SALT), keyDerivationPrf, 65536, 32);
后者适用于V4.6.1及更高版本,但您需要
Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivation
-class你可以找到例如在https://www.nuget.org/packages/Microsoft.AspNetCore.Cryptography.KeyDerivation/。对于安装,您可以
使用例如软件包管理器控制台(工具-NuGet软件包管理器-软件包管理器控制台)。只需按链接中所述输入相应的命令。
也许您会收到IDE错误
CS0012
。在这种情况下,必须将<Reference Include="netstandard" />
添加到csproj
文件的参考部分(另请参见https://github.com/dotnet/standard/issues/542)。 KeyDerivationPrf
类不限制盐长度。还有其他我没有尝试过的可能性(例如Bouncy Castle),但也许它们是您的更好选择。在Rfc2898 / PBKDF2 with SHA256 as digest in c#上也讨论了该主题。
3)C#加密方法的一个示例是:
public string Encrypt(string plainText)
{
// PBKDF2WithHmacSHA256 Key derivation
// ...
using (RijndaelManaged cipher = new RijndaelManaged())
{
cipher.Key = secretKey;
cipher.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
cipher.Mode = CipherMode.CBC;
cipher.Padding = PaddingMode.PKCS7;
byte[] encryptedData;
using (ICryptoTransform encryptor = cipher.CreateEncryptor())
{
using (System.IO.MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(plainText);
}
encryptedData = memoryStream.ToArray();
}
}
}
return Convert.ToBase64String(encryptedData);
}
}
其中,
plainText
是包含纯文本(与strToEncrypt
对应)的字符串。加密的数据将进行base64编码,并以字符串形式返回(类似于Java方法)。测试用例:
String KEY = "The Password";
String SALT = "The Salt";
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
给
Plain text: This is a plain text that needs to be encrypted
Key (hex): 2D7664713D701C58FC506F93CEA3194671AD3B5C034255A4AC04AF46EADC89BC
Base64 encoded
encrypted data: ksUYjmbP9ga39LXr3wXQ34Bp32UlloYPxg3WWuW0iovWbg/GxHJrIuF3jrDvjr/Q
4)C#解密方法的一个示例是:
public string Decrypt(string encryptedText)
{
// PBKDF2WithHmacSHA256 Key derivation
// ...
using (RijndaelManaged cipher = new RijndaelManaged())
{
cipher.Key = secretKey;
cipher.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
cipher.Mode = CipherMode.CBC;
cipher.Padding = PaddingMode.PKCS7;
string decryptedText;
using (ICryptoTransform decryptor = cipher.CreateDecryptor())
{
using (System.IO.MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(encryptedText)))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
decryptedText = streamReader.ReadToEnd();
}
}
}
}
return decryptedText;
}
}
其中,
encryptedText
是加密部分的返回值(base64编码的加密数据,对应于strToDecrypt
)。该方法返回解密的文本(类似于Java方法)。