c# java interop aes encryption-symmetric

c# - Cifrado/descifrado Interop entre Java/Net con AES y especificando IV y Key



encryption-symmetric (0)

Estoy tratando de implementar cifrado simétrico usando AES donde especifico una clave y IV. Dentro de cada ecosistema (Java -> Java / .NET -> .NET) el cifrado y el descifrado funcionan como están diseñados, pero si trato de ir entre los dos, recibo una serie de errores con respecto al relleno, etc. (detalles a continuación).

He leído varias publicaciones, entre ellas http://blogs.msdn.com/b/dotnetinterop/archive/2005/01/24/java-and-net-aes-crypto-interop.aspx pero ninguna parece tener el mismo caso de uso . Aquí está mi código:

JAVA

public class Main { public static void main(String[] args) throws Exception { String data = "Something to decrypt"; String encrypt = Encrypt(data); System.out.println(encrypt); String decrypt = Decrypt(encrypt); System.out.println(decrypt); } private static String Encrypt(String raw) throws Exception { Cipher c = getCipher(Cipher.ENCRYPT_MODE); byte[] encryptedVal = c.doFinal(raw.getBytes("UTF-8")); return new BASE64Encoder().encode(encryptedVal); } private static Cipher getCipher(int mode) throws Exception { Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding", new SunJCE()); //a random Init. Vector. just for testing byte[] iv = "e675f725e675f725".getBytes("UTF-8"); c.init(mode, generateKey(), new IvParameterSpec(iv)); return c; } private static String Decrypt(String encrypted) throws Exception { byte[] decodedValue = new BASE64Decoder().decodeBuffer(encrypted); Cipher c = getCipher(Cipher.DECRYPT_MODE); byte[] decValue = c.doFinal(decodedValue); return new String(decValue); } private static Key generateKey() throws Exception { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); char[] password = "Pass@word1".toCharArray(); byte[] salt = "S@1tS@1t".getBytes("UTF-8"); KeySpec spec = new PBEKeySpec(password, salt, 65536, 128); SecretKey tmp = factory.generateSecret(spec); byte[] encoded = tmp.getEncoded(); return new SecretKeySpec(encoded, "AES"); } }

.RED

internal class Program { private static void Main(string[] args) { string encrypted = Encrypt("Something to decrypt"); Console.Out.WriteLine(encrypted); string decrypted = Decrypt(encrypted); Console.Out.WriteLine(decrypted); Console.Out.WriteLine("Press any key to continue"); Console.ReadKey(); } private static string Encrypt(string raw) { using (var csp = new AesCryptoServiceProvider()) { ICryptoTransform e = GetCryptoTransform(csp, true); byte[] inputBuffer = Encoding.UTF8.GetBytes(raw); byte[] output = e.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length); string encrypted = Convert.ToBase64String(output); return encrypted; } } public static string Decrypt(string encrypted) { using (var csp = new AesCryptoServiceProvider()) { var d = GetCryptoTransform(csp, false); byte[] output = Convert.FromBase64String(encrypted); byte[] decryptedOutput = d.TransformFinalBlock(output, 0, output.Length); string decypted = Encoding.UTF8.GetString(decryptedOutput); return decypted; } } private static ICryptoTransform GetCryptoTransform(AesCryptoServiceProvider csp, bool encrypting) { csp.Mode = CipherMode.CBC; csp.Padding = PaddingMode.PKCS7; var passWord = "Pass@word1"; var salt = "S@1tS@lt"; //a random Init. Vector. just for testing String iv = "e675f725e675f725"; var spec = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(passWord), Encoding.UTF8.GetBytes(salt), 65536); byte[] key = spec.GetBytes(16); csp.IV = Encoding.UTF8.GetBytes(iv); csp.Key = key; if (encrypting) { return csp.CreateEncryptor(); } return csp.CreateDecryptor(); } }

Los resultados de las aplicaciones son:

JAVA

EO88Y8EjPAbaiZGoQM47z5i3vvy8jgVoehCPJDQES/4= Something to decrypt

.RED

T/m/GatOCvFEJ4frVIoY8CbuQ1av97HoKdhUhAZcXp0= Something to decrypt

Cuando trato de descifrar la cadena .NET en Java, obtengo: Excepción en el hilo "main" javax.crypto.BadPaddingException: dado que el bloque final no está adecuadamente acolchado.

En .NET, me sale de manera similar: System.Security.Cryptography.CryptographicException no fue manejado HResult = -2146233296 Message = Padding no es válido y no se puede eliminar.

En .NET, uso Rfc2898DeriveBytes para generar mi clave en función de la contraseña, sal y número de iteraciones. Supongo que esta es la causa raíz, ya que en Java utilizo SecretKeyFactory con la esperanza de lograr el mismo resultado. Sin embargo, si esta es la causa, no estoy seguro de cómo conciliar los dos ...?

Gracias por cualquier ayuda.

** ACTUALIZADO - RESUELTO **

Chico, me siento más tonto de lo normal. El problema fue un error tipográfico en mi código. El valor de sal de .NET tiene un ''1'' y una ''L'' donde el valor de sal de Java tiene un ''1'' y un ''1''. Corregir este error solucionó el problema. Perdón por perder el tiempo de alguien.

.RED

var salt = "S@1tS@lt";

Java

byte[] salt = "S@1tS@1t"