我想使用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方法)。

10-07 19:27
查看更多