programa para librerias encriptar encriptacion ejemplo cifrado algoritmos java android performance encryption cryptography

encriptacion - librerias para encriptar en java



¿Por qué el cifrado/descifrado AES es 3 veces más lento en Android 24+? (2)

Puedes saltar a TL; DR

Tenemos una aplicación que se basa en gran medida en el cifrado y descifrado AES. Queremos admitir tantos dispositivos como sea posible, pero algunos de ellos (especialmente las tabletas de mala calidad y no solo me refiero a los no-nombres chinos, sino que también a algunas tabletas de gama baja de Samsung o Lenovo) simplemente demoran en cifrar y descifrar.

Hemos utilizado Android 23 en nuestra aplicación y pudimos identificar algún tipo de nivel por debajo del cual nuestra aplicación simplemente no funcionará bien para el usuario final (tendrían que esperar demasiado tiempo para que aparezca el contenido). Teníamos que descartar muchas tabletas para usarlas con nuestra aplicación, pero bueno, pudimos vivir con eso.

Recientemente, algunas de nuestras dependencias comenzaron a requerir una versión más nueva de Android. Por ejemplo, queríamos cambiar a Facebook Core SDK, en lugar del completo SDK de Facebook para ahorrar algo de espacio. Pero depende del paquete de soporte de Android v25 y no podremos compilarlo porque proguard se niega a procesar las fuentes.

Así que se tomó la decisión de mover el proyecto a un Android más nuevo. Fue bastante suave, además del impacto en el rendimiento que tuvo en nuestro mecanismo de cifrado / descifrado. De repente fue mucho más lento. Las tabletas que calificaríamos como "que funcionan lo suficientemente bien" eran extremadamente lentas.

TL; DR

Comencé a investigar qué sucedió durante nuestra migración de Android 23 a Android 26, lo que causaría una gran caída en el rendimiento del cifrado / descifrado AES.

He creado una aplicación, que funciona como una especie de punto de referencia. Al hacer un cambio simple:

  • compileSdkVersion 23->26
  • targetSdkVersion 23->26
  • compile ''com.android.support:appcompat-v7:VERSION'' 23.4.0 -> 26.+

La caída del rendimiento es enorme.

Aquí hay un ejemplo de resultado de una de las tabletas:

Android 23: 136959 B/s Android 26: 34419 B/s

Eso es casi 4x más lento. Puedo reproducir estos resultados en todos los dispositivos que tengo que probar. Claro, en los dispositivos nuevos de alto rendimiento es apenas visible, pero en los dispositivos antiguos, está claro.

He buscado en la web cualquier detalle sobre esto, pero no he encontrado nada. Realmente agradecería a alguien que arroje algo de luz sobre este tema.

Realmente espero haber cometido un error en alguna parte, pero no pude encontrarlo.

Para el cifrado / descifrado, usamos la biblioteca SpongyCastle.

Las fuentes de mi aplicación Crypto Tester están disponibles en GitHub: https://github.com/krstns/cryptoTester

master_26 rama master con la configuración de Android 23 y la rama master_26 con la configuración de Android 26.

Para completar, pegaré aquí el método que se usa para el descifrado:

/** * Decrypt the given data with the given key * * @param data The data to decrypt * @return The decrypted bytes */ public static byte[] decrypt(byte[] data, byte[] key, byte[] iv) { if (key == null || iv == null) { throw new AssertionError("DECRYPT: Key or iv were not specified."); } // make sure key is AES256 byte[] bookKeyData = new byte[32]; byte[] outBuf; System.arraycopy(key, 0, bookKeyData, 0, key.length); try { PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine())); cipher.init(false, new ParametersWithIV(new KeyParameter(bookKeyData), iv)); int outputSize = cipher.getOutputSize(data.length); outBuf = new byte[cipher.getOutputSize(outputSize)]; int processed = cipher.processBytes(data, 0, data.length, outBuf, 0); if (processed < outputSize) { processed += cipher.doFinal(outBuf, processed); } return Arrays.copyOfRange(outBuf, 0, processed); } catch (Exception e) { e.printStackTrace(); } return null; }

Ah y ... sí. Soy consciente de que esto es CBC, soy consciente de por qué no se debe usar, etc. Actualmente, se hace a propósito. Este no es el tema de la pregunta, así que no vayamos allí.


Finalmente he encontrado una solución.

Cuando intenté crear un problema en SpongyCastle GitHub, noté que hay versiones más nuevas que la 1.54 ... Bueno, tonta por no haber investigado esto antes.

Solo una advertencia, no funcionó de inmediato en mi proyecto principal. El mecanismo de cifrado / descifrado es parte de un proyecto de biblioteca que luego se incluye en mi proyecto principal. Por favor, recuerde actualizar también su proyecto principal, o de lo contrario seguirá siendo muy lento.

Así me funcionó después de:

  • cambiando la versión del castillo esponjoso a 1.56
  • cambiando compileSdkVersion a 26
  • cambiando buildToolsVersion a 26.0.2
  • cambiando targetSdkVersion a 26

En ambos, proyecto de biblioteca y proyecto principal.


Parece que estás usando SpongyCastle directamente. SpongyCastle es la versión de Android de BouncyCastle (BC). Sin embargo, BC es una implementación de algoritmos criptográficos y las API de utilidad circundantes, solo para software .

Si realmente desea acelerar los cálculos de AES, debería utilizar la API de seguridad de Java en su lugar, por ejemplo, utilizando la clase javax.crypto.Cipher . Esto permitirá la aceleración de hardware y la ejecución de código nativo en plataformas compatibles. En general, se tratará de todas las plataformas, ya que la funcionalidad de criptografía principal se implementa utilizando las bibliotecas OpenSSL en las plataformas más nuevas.

En general, se recomienda usar solo las API "ligeras" de Bouncy Castle (como las implementaciones de software AES que está usando) siempre que la funcionalidad requerida no esté disponible dentro de los proveedores de Criptografía provistos. Este definitivamente no es el caso de algoritmos como AES / CBC.

Actualmente, su biblioteca depende de la ejecución del código de bytes de la implementación de Bouncy Castle, que es mucho más lenta. Tenga en cuenta también que a Bouncy Castle no le gustan mucho los entornos de depuración, así que asegúrese de que se ejecute sin demoras al probar el rendimiento, si es posible sin el soporte del depurador.