2011-06-30 41 views
11

Soy nuevo en tecnología de cifrado. Encontré este código para hacer el cifrado simétrico.Java utilizando el cifrado de clave simétrica AES 256 y 128

byte[] key = //... secret sequence of bytes 
byte[] dataToSend = ... 
Cipher c = Cipher.getInstance("AES"); 
SecretKeySpec k = new SecretKeySpec(key, "AES"); 
c.init(Cipher.ENCRYPT_MODE, k); 
byte[] encryptedData = c.doFinal(dataToSend); 

Its working. Aquí puedo usar mi propia contraseña. Y eso es exactamente lo que necesitaba. Pero no sé cómo hacer 128 o 256 Symmetric Enctryption. ¿Cómo puedo usar las llaves 128 y 256 en mi código?

+0

Realmente no sé, pero creo que el uso de una clave de 256 bytes hará el trabajo. –

+0

en realidad, solo la clave de 16 bytes (128 bits) está funcionando en mi código. – Bhuban

+0

¿Qué es "no funciona" con teclas más grandes? ¿Recibes una excepción? ¿cúal? ¿Cuál es su mensaje y seguimiento de la pila? –

Respuesta

13

Si AES usa el modo de 128 o 256 bits depende del tamaño de su clave, que debe tener 128 o 256 bits de longitud. Normalmente, no utiliza su contraseña como clave, ya que las contraseñas rara vez tienen la longitud exacta que necesita. En cambio, deriva la clave de cifrado de su contraseña mediante el uso de alguna función de derivación de clave.

Ejemplo muy simple: tome MD5 de su contraseña para obtener la clave de 128 bits. Si desea una clave de 256 bits, puede usar SHA-256 para obtener un hash de 256 bits de su contraseña. Las funciones de derivación de teclas generalmente ejecutan este hashing varias veces y también usan sal extra. Consulte http://en.wikipedia.org/wiki/Key_derivation_function para más detalles.

También tenga en cuenta que para ejecutar un cifrado de más de 128 bits deberá descargar e instalar 'Java Cryptography Extension (JCE) Archivos de Política de Jurisdicción de Intensidad Ilimitada 6' de http://www.oracle.com/technetwork/java/javase/downloads/index.html.

+5

MD5? ¿Me desperté en 1996 esta mañana? La familia SHA tiene algoritmos que producen hashes de 128, 256, 348 y 512 bits. –

+4

@Peter: fue solo un ejemplo rápido de cómo obtener la clave de 128 bits a partir de la contraseña. Si su contraseña tiene menos de 16 bytes, también puede rellenarla con 16 bytes. Estás retocando detalles sin importancia. (De todos modos, he actualizado mi respuesta para decir que use SHA-256 para obtener la clave de 256 bits de la contraseña) –

+1

@Peter, jajaja, sí, odio ver a MD5 en cualquier cosa que no sea el código heredado, y no creo que deba ser recomendado para principiantes; Ha sido hace mucho tiempo roto. –

2

Se puede utilizar un simple objeto KeyGenerator así:

KeyGenerator generator = KeyGenerator.getInstance("AES/CTR/PKCS5PADDING"); 
generator.init(128); 
SecretKey key = generator.generateKey(); 
Cipher cipher = Cipher.getInstance("AES"); 
cipher.init(Cipher.ENCRYPT_MODE, key); 
... 
+1

¿Cómo puedo usar mi propia contraseña? – Bhuban

1

De Java's docs for Cipher.init(...):

pública final void init (int OPMODE, clave Key)

Lanza: InvalidKeyException - si la clave dada es inapropiada para inicializar este cifrado, o si este cifrado es siendo inicializado para el descifrado y requiere parámetros del algoritmo que no se puede determinar a partir de la clave dada , o si la clave dada tiene un tamaño de clave que excede el máximo keysize permisible (como se determina a partir de los archivos de política de jurisdicción configurados).

Para mí, esto significa que, como se dijo Martijn Courteaux en su comentario, usted debe utilizar una clave de 256 bits (es decir, inicializar el SecretKeySpec con una matriz de bytes que contiene 32 bytes), y la cifra va a aceptarlo y úselo, o rechace y haga una excepción si su tamaño no es aceptable.

Si obtiene una excepción, es probable que sea porque no ha instalado los archivos cifrados de fuerza ilimitada (la instalación JDK predeterminada permite claves de 128 bits como se documenta en este crypto spec document). Descargue el paquete crypto de intensidad ilimitada here.

+0

Sí, mi código puede tomar exactamente 16 bytes o 128 bits. ¿Entonces esa era mi pregunta de cómo usar la clave de 256 bits? – Bhuban

+0

Edité mi respuesta –

+0

Gracias. Está funcionando ahora. Tu respuesta fue realmente útil. – Bhuban

0
public class CipherUtils 
{ 
    private static byte[] key = { 
      0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 
    };//"thisIsASecretKey"; 

    public static String encrypt(String strToEncrypt) 
    { 
     try 
     { 
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 
      final SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
      cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
      final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes())); 
      return encryptedString; 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 
+0

Tengo un par de preguntas. 1. Esa clave es la única clave que se puede usar para descifrar, ¿verdad? (Probablemente una respuesta obvia a esa pregunta, simplemente asegurándose) 2. Si los mismos datos se cifran utilizando esa misma clave (dos veces diferentes ejecutando el método), ¿procesa diferentes bytes cifrados? – raddevus

+0

Bueno, convertí ese código y me di cuenta de las respuestas. Además, es interesante que el ejemplo de OWASP (https://www.owasp.org/index.php/Using_the_Java_Cryptographic_Extensions) mencione directamente el uso del IV (vector de inicialización) pero no se usa en el código de esta respuesta. CE la vie. – raddevus

+0

No codifique una clave secreta. Estará trivialmente disponible para cualquier persona que tenga acceso al código compilado. – Mike

6

la respuesta para 128 bits

El siguiente método es para cifrar una cadena (valueEnc) con el cifrado AES:

private static final String ALGORITHM = "AES"; 

public String encrypt(final String valueEnc, final String secKey) { 

    String encryptedVal = null; 

    try { 
     final Key key = generateKeyFromString(secKey); 
     final Cipher c = Cipher.getInstance(ALGORITHM); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     final byte[] encValue = c.doFinal(valueEnc.getBytes()); 
     encryptedVal = new BASE64Encoder().encode(encValue); 
    } catch(Exception ex) { 
     System.out.println("The Exception is=" + ex); 
    } 

    return encryptedVal; 
} 

El siguiente método descifrará la cadena cifrada AES (encryptedVal) :

public String decrypt(final String encryptedValue, final String secretKey) { 

    String decryptedValue = null; 

    try { 

     final Key key = generateKeyFromString(secretKey); 
     final Cipher c = Cipher.getInstance(ALGORITHM); 
     c.init(Cipher.DECRYPT_MODE, key); 
     final byte[] decorVal = new BASE64Decoder().decodeBuffer(encryptedValue); 
     final byte[] decValue = c.doFinal(decorVal); 
     decryptedValue = new String(decValue); 
    } catch(Exception ex) { 
     System.out.println("The Exception is=" + ex); 
    } 

    return decryptedValue; 
} 

El secKey es una clave de 128 bits, que está codificada en el BASE64Encoder. El BASE64Decoder en el siguiente método genera una adecuada clave de 128 bits

private Key generateKeyFromString(final String secKey) throws Exception { 
    final byte[] keyVal = new BASE64Decoder().decodeBuffer(secKey); 
    final Key key = new SecretKeySpec(keyVal, ALGORITHM); 
    return key; 
} 
+1

Ha olvidado utilizar un vector de inicialización y tampoco ha especificado el modo y el relleno de AES que desea utilizar. Si bien esta es una respuesta a la pregunta, tenga en cuenta que este no es ** un uso seguro del cifrado. –

Cuestiones relacionadas