gcm example decryption code cipher java encryption aes

example - aes java implementation



Cómo implementar el cifrado AES Java de 256 bits con CBC (2)

He realizado proyectos similares en un midlet anteriormente, tengo los siguientes consejos para ti:

  1. No hay una forma segura de almacenar secretos compartidos en el teléfono. Puedes usarlo pero esto cae en una categoría llamada Seguridad a través de la oscuridad . Es como un tipo de seguridad "clave debajo del tapete".
  2. No use AES de 256 bits, que no está ampliamente disponible. Es posible que deba instalar otra JCE. AES o TripleDES de 128 bits aún se consideran seguros. Teniendo en cuenta el número 1, no debe preocuparse por esto.
  3. El cifrado con una contraseña (diferente para cada usuario) es mucho más seguro. Pero no debe usar la contraseña como la clave que muestra en el ejemplo. Utilice PBEKeySpec (encriptación basada en contraseña) para generar las claves.
  4. Si solo te preocupan los ataques MITM (man-in-the-middle), usa SSL.

He leído los siguientes temas y me han ayudado un poco, pero estoy buscando un poco más de información.

Cómo escribir cifrado y descifrado AES / CBC / PKCS5Pad con el parámetro de vectorización de inicialización para BlackBerry

Cifrado Java AES de 256 bits

Básicamente, lo que estoy haciendo es escribir un programa que codificará una solicitud que se enviará a través de TCP / IP, y luego se descifrará mediante un programa de servidor. La encriptación necesitará ser AES, y al hacer una investigación descubrí que necesito usar CBC y PKCS5Padding. Básicamente, necesito una clave secreta y una IV también.

La aplicación que estoy desarrollando es para un teléfono, por lo que quiero usar los paquetes de seguridad de Java para mantener el tamaño bajo. Ya terminé el diseño, pero no estoy seguro de la implementación del IV y la clave compartida.

Aquí hay un código:

// My user name byte[] loginId = "login".getBytes(); byte[] preSharedKey128 = "ACME-1234AC".getBytes(); byte[] preSharedKey192 = "ACME-1234ACME-1234A".getBytes(); // 256 bit key byte[] preSharedKey256 = "ACME-1234ACME-1234ACME-1234".getBytes(); byte[] preSharedKey = preSharedKey256; // Initialization Vector // Required for CBC byte[] iv ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; IvParameterSpec ips = new IvParameterSpec(iv); byte[] encodedKey = new byte[loginId.length + preSharedKey.length]; System.arraycopy(loginId, 0, encodedKey, 0, loginId.length); System.arraycopy(preSharedKey, 0, encodedKey, loginId.length, preSharedKey.length); // The SecretKeySpec provides a mechanism for application-specific generation // of cryptography keys for consumption by the Java Crypto classes. // Create a key specification first, based on our key input. SecretKey aesKey = new SecretKeySpec(encodedKey, "AES"); // Create a Cipher for encrypting the data using the key we created. Cipher encryptCipher; encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Initialize the Cipher with key and parameters encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey, ips); // Our cleartext String clearString = "33,8244000,9999,411,5012022517,0.00,0,1,V330"; byte[] cleartext = clearString.getBytes(); // Encrypt the cleartext byte[] ciphertext = encryptCipher.doFinal(cleartext); // Now decrypt back again... // Decryption cipher Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Initialize PBE Cipher with key and parameters decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ips); // Decrypt the cleartext byte[] deciphertext = decryptCipher.doFinal(ciphertext);

En pocas palabras, lo que debe hacer es encriptar algún mensaje que pueda descifrar el servidor sin que el servidor tenga que obtener una clave o IV del teléfono. ¿Hay alguna manera de que yo pueda hacer esto donde pueda asegurar la IV y la llave en el teléfono, y aún así tener la clave y IV conocidas por el servidor también? Siéntase libre de decirme que deje las cosas más claras si no lo son.


Hay algunos problemas con el código. En primer lugar, debería usar un generador de claves para generar claves secretas. Usar solo texto directamente podría funcionar para algunos algoritmos, pero otros tienen claves débiles y otros que necesitan ser probados.

Incluso si desea hacer un cifrado basado en contraseñas, la contraseña debe ejecutarse a través de un algoritmo de derivación de clave para producir una clave, como se muestra en mi respuesta a la pregunta que ya citó.

Además, no deberías usar el método no-arg getBytes() de String . Esto depende de la plataforma. Si todas las cadenas que está codificando contienen solo caracteres del conjunto de caracteres US-ASCII, aclárelo especificando esa codificación explícitamente. De lo contrario, si las plataformas del teléfono y del servidor usan codificaciones de caracteres diferentes, la clave y IV no se mostrarán igual.

Para el modo CBC, es mejor usar una nueva IV para cada mensaje que envíe. Por lo general, los CBC IV se generan aleatoriamente. Otros modos como CFB y OFB requieren IV únicos para cada mensaje. Por lo general, los IV se envían con el texto cifrado. Los IV no necesitan mantenerse en secreto, pero muchos algoritmos se romperán si se usa un IV predecible.

El servidor no necesita obtener el secreto o IV directamente del teléfono. Puede configurar el servidor con la clave secreta (o contraseña, de la cual se deriva la clave secreta), pero en muchas aplicaciones, este sería un mal diseño.

Por ejemplo, si la aplicación va a implementarse en los teléfonos de varias personas, no es una buena idea que usen la misma clave secreta. Un usuario malintencionado puede recuperar la clave y romper el sistema para todos.

Un mejor enfoque es generar nuevas claves secretas en el teléfono y utilizar un algoritmo de acuerdo clave para intercambiar la clave con el servidor. El acuerdo de clave Diffie-Hellman se puede usar para esto, o la clave secreta se puede encriptar con RSA y enviar al servidor.

Actualizar:

Diffie-Hellman en el modo "estático-efímero" (y el modo "estático estático" también, aunque es menos deseable) es posible sin un mensaje inicial del servidor al teléfono, siempre que la clave pública del servidor esté incorporada en la aplicación .

La clave pública del servidor no presenta el mismo riesgo que la incrustación de una clave secreta común en el teléfono. Como se trata de una clave pública, la amenaza sería que un atacante tuviera en sus manos (o hackeara de forma remota) el teléfono y reemplazara la clave pública real con una clave falsa que le permita suplantar al servidor.

Puede usarse el modo estático estático, pero en realidad es más complicado y un poco menos seguro. Cada teléfono necesitaría su propio par de claves único, o volverás a caer en el problema de la clave secreta. Al menos no habría necesidad de que el servidor realizara un seguimiento de qué teléfono tiene qué tecla (suponiendo que exista algún mecanismo de autenticación a nivel de aplicación, como una contraseña).

No sé qué tan rápido son los teléfonos. En mi escritorio, generar un par de claves efímeras toma aproximadamente 1/3 de segundo. Generar parámetros Diffie-Hellman es muy lento; definitivamente querrá volver a usar los parámetros de la clave del servidor.