Equivalentes de cifrado / descifrado en Java para construcciones C #
Tengo un mp4 cifrado usando Rijndael y estoy descifrando en C # de la siguiente manera.
System.Security.Cryptography.Rijndael crypt = System.Security.Cryptography.Rijndael.Create(); crypt.Key = convertedSecureString; byte[] initializationVectorLength = new byte[sizeof(int)]; CryptoStream cryptostream = new CryptoStream(inputStream, crypt.CreateDecryptor(), CryptoStreamMode.Read); byte[] buffer = new byte[1024]; int len; while ((len = cryptostream.Read(buffer, 0, buffer.Length)) > 0) { outputStream.Write(buffer, 0, len); buffer = new byte[1024]; } outputStream.Flush(); cryptostream.Close(); inputStream.Close();
Ahora necesito convertir este código a equivalente de Java / Android. No estoy seguro de por dónde empezar francamente. Estoy confundido por tantas opciones – algunos dicen utilizar Bouncy Castle, algunos dicen Apache Commons, algunos de la lib nativa de Java. Cómo hago esto. ¿Y qué hago sobre CryptoStream etc?
- ¿Cómo saber si estoy conectado correctamente a mi número de salida en Android?
- Cómo crear una tabla dinámica de datos en android?
- EXCEPCIÓN FATAL: main java.lang.VerifyError: net.sourceforge.jtds.jdbc.TdsCore
- Analizar fecha en android
- Android spinner Data Binding utilizando XML y mostrar los valores seleccionados
ACTUALIZAR
Estoy utilizando el siguiente código en C # para asignar la clave
byte[] convertedSecureString = new byte[this.key.Length]; IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(this.key); for (int i = 0, j = 0; i < this.key.Length * UnicodeByteLength; i = i + UnicodeByteLength, j++) { convertedSecureString[j] = System.Runtime.InteropServices.Marshal.ReadByte(ptr, i); } try { crypt.Key = convertedSecureString; }
donde la llave es segura. Tengo la clave no segura equivalente en Java. ¿Cómo puedo convertir este pedazo de código a Java
ACTUALIZAR
Rfc2898DeriveBytes newKey = new Rfc2898DeriveBytes(crypt.Key.ToString(), crypt.IV); Array.Copy(newKey.GetBytes((int)crypt.KeySize / 8), crypt.Key, (int)crypt.KeySize / 8); Array.Copy(newKey.GetBytes((int)crypt.BlockSize / 8), crypt.IV, (int)crypt.BlockSize / 8);
Estoy usando esto en C # para modificar la clave utilizando Rfc 2898 y derivar los bytes – No puedo encontrar un equivalente en Java – He encontrado aquí Java equivalente de C # Rfc2898DerivedBytes en el segundo comentario -, pero ¿qué valores doy para iterator y dklen?
- Ical parser android
- ¿Cómo configurar el nombre del hilo?
- Servicio ha filtrado IntentReceiver en android
- BitmapFactory.decodeResource devuelve un mapa de bits mutable en Android 2.2 y un mapa de bits inmutable en Android 1.6
- Android Linkify - números de teléfono que se pueden hacer clic
- ¿Existe una utilidad o API para convertir abreviaturas abreviadas de SMS a oraciones adecuadas?
- Deserialización polimórfica de JSON con jackson, tipo de propiedad se convierte en "null"
- Cambio de programación de las pestañas de la barra de acción: cómo adjuntar un argumento?
Necesitas obtener el objeto Cipher . Aquí hay una manera de obtenerlo, usando byte[] aesKey
y byte[] iv
(vector de inicialización, siempre debe ser de 16 bytes para AES).
// aesKey is 128, 196 or 256-bit key (8, 12 or 16 byte array) SecretKeySpec key = new SecretKeySpec(aesKey, "AES"); // initialization vector IvParameterSpec ivSpec = new IvParameterSpec(iv); // create and initialize cipher object Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
Una vez que tenga el objeto Cipher
en el modo de descifrado, puede alimentarlo con datos cifrados mediante métodos de update
y le devolverá los datos de texto sin formato. Cuando haya terminado, debe llamar a uno de los métodos doFinal
para obtener el bloque final.
Como alternativa, puede crear CipherInputStream
utilizando su objeto Cipher y el flujo de entrada original que suministra datos cifrados. Usted lee los datos de CipherInputStream
, que a su vez lee los datos del flujo de entrada original, descifra y devuelve los datos de texto sin formato.
Para encriptar, debe pasar Cipher.ENCRYPT_MODE
al método Cipher.init
y utilizar CipherOutputStream
en CipherOutputStream
lugar.
Actualización: ejemplo completo, más o menos equivalente al código original de C #:
// Algorithm, mode and padding must match encryption. // Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); // If you have Bouncycastle library installed, you can use // Rijndael/CBC/PKCS7PADDING directly. Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7PADDING"); // convertedSecureString and initVector must be byte[] with correct length cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(convertedSecureString, "AES"), new IvParameterSpec(initVector)); CipherInputStream cryptoStream = new CipherInputStream(inputStream, cipher); byte[] buffer = new byte[1024]; int len = cryptoStream.read(buffer, 0, buffer.length); while (len > 0) { outputStream.write(buffer, 0, len); len = cryptoStream.read(buffer, 0, buffer.length); } outputStream.flush(); cryptoStream.close(); // no need to close inputStream here, as cryptoStream will close it
De forma predeterminada, Java no admite el algoritmo Rijndael (AES puede o no funcionar, ver la otra respuesta) y PKCS7 relleno. Usted necesitará instalar la extensión de Bouncycastle para eso y después apenas utilizar Cipher.getInstance("Rijndael/CBC/PKCS7PADDING");
. ¿Por qué CBC y PKCS7 Padding? Parecen ser los valores predeterminados para System.Security.Cryptography.Rijndael clase. Si me equivocó, utilice el modo correcto y el relleno para su situación.
No se preocupe por la implementación en C #. Vaya a través del siguiente enlace para cifrar / descifrar Java Language. Implementación de RjIndeal en Java