2011-11-10 35 views
5

Por ciertas razones necesito implementar Rijndael de/compression con un tamaño de bloques de 256 bits en lugar de AES que usa un tamaño de bloque de 128 bits (razón: los datos se cifran en PHP usando Rijndael ...).¿Cómo encriptar o desencriptar con Rijndael y un tamaño de bloque de 256 bits?

¿Cómo puedo cambiar el tamaño del bloque para un cifrado?

Si acabo de obtener un cifrado con "RIJNDAEL/CFB/PKCS5Padding" y trato de inicializar un IV con 256 bits obtengo una excepción, porque el tamaño del bloque es de solo 128 bits.

+0

Usted probablemente tendrá que asegurarse de haber instalado las clases de cifrado ilimitada de Java JCE . No son parte de la típica distribución Java estándar porque son ilegales en algunos países. – Romain

+0

allready have them. Todavía no puedo encontrar cómo obtener un objeto de cifrado con el tamaño de bloques requerido. – Laures

+0

Luego, creo que @GregS tiene la respuesta. Creía que Rijndael-256 era parte de JCE Unlimited Providers, pero estoy acostumbrado a utilizar el Java algo personalizado de mi empresa, que tiene un proveedor de JCE, pero puede ser una implementación privada. – Romain

Respuesta

13

No existe soporte en ninguno de los proveedores de Sun JCE para otra cosa que no sea Rijndael con el tamaño de bloques de 128 bits: este es el algoritmo AES. Para obtener rijndael con el tamaño de bloque de 256 bits, tendrá que ir a otro lugar. Sugiero la biblioteca Bouncycastle java. La clase RijndaelEngine tiene un constructor que acepta un tamaño de bloque en bits. La mayoría de las personas considera que la clase PaddedBufferedBlockCipher es más conveniente cuando se utiliza con relleno adecuado, p.

PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new RijndaelEngine(256), new PKCS7Padding()); 
0

Tenga en cuenta que PHP mcrypt utiliza el relleno de bytes cero para que new ZeroBytePadding() se debe utilizar en lugar de new PKCS7Padding().

Fuelle una implementación completa usando CBC y RIJNDAEL 256.

import org.bouncycastle.crypto.CipherParameters; 
import org.bouncycastle.crypto.InvalidCipherTextException; 
import org.bouncycastle.crypto.engines.RijndaelEngine; 
import org.bouncycastle.crypto.modes.CBCBlockCipher; 
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; 
import org.bouncycastle.crypto.paddings.ZeroBytePadding; 
import org.bouncycastle.crypto.params.KeyParameter; 
import org.bouncycastle.crypto.params.ParametersWithIV; 
import org.bouncycastle.util.encoders.Base64; 

public static String encryptWithAesCBC(String plaintext, String key, String iv) 
{ 
    try { 
     PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding()); 
     CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes()); 
     cipher.init(true, ivAndKey); 
     return new String(Base64.encode(cipherData(cipher, plaintext.getBytes()))); 
    } catch (InvalidCipherTextException e) { 
     throw new RuntimeException(e); 
    } 
} 

public static String decryptWithAesCBC(String encrypted, String key, String iv) 
{ 
    try { 
     byte[] ciphertext = Base64.decode(encrypted); 
     PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding()); 

     CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes()); 
     aes.init(false, ivAndKey); 
     return new String(cipherData(aes, ciphertext)); 
    } catch (InvalidCipherTextException e) { 
     throw new RuntimeException(e); 
    } 
} 

private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data) throws InvalidCipherTextException 
{ 
    int minSize = cipher.getOutputSize(data.length); 
    byte[] outBuf = new byte[minSize]; 
    int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0); 
    int length2 = cipher.doFinal(outBuf, length1); 
    int actualLength = length1 + length2; 
    byte[] cipherArray = new byte[actualLength]; 
    for (int x = 0; x < actualLength; x++) { 
     cipherArray[x] = outBuf[x]; 
    } 
    return cipherArray; 
} 

private String md5(String string) 
{ 
    try { 
     java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); 
     byte[] array = md.digest(string.getBytes()); 
     StringBuffer sb = new StringBuffer(); 
     for (int i = 0; i < array.length; ++i) { 
      sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3)); 
     } 
     return sb.toString(); 
    } catch (java.security.NoSuchAlgorithmException e) { 
     throw new RuntimeException(e); 
    } 
} 

Al utilizar CFB, PaddedBufferedBlockCipher debe ser reemplazado por el siguiente:

PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CFBBlockCipher(new RijndaelEngine(256),8), new ZeroBytePadding()); 
// PHP mcrypt uses a blocksize of 8 bit for CFB 

Uso:

String salt = "fbhweui3497"; 
String key = md5(salt); 
String iv = md5(md5(salt)); 

String encrypted = encryptWithAesCBC("text to encript", key, iv); 

String decrypted = decryptWithAesCBC(encrypted, key, iv); 
+1

¿Puede proporcionar el md5()? Cadena md5 (Entrada de cadena) { \t \t Cadena resultado = entrada; \t \t MessageDigest md; \t \t try { \t \t \t md = MessageDigest.getInstance ("MD5"); \t \t \t md.update (input.getBytes()); \t \t \t BigInteger hash = new BigInteger (1, md.digest()); \t \t \t resultado = hash.toString (16); \t \t \t while (resultado.length() <32) {// 40 para SHA-1 \t \t \t \t result = "0" + result; \t \t \t} \t \t} catch (NoSuchAlgorithmException e) { \t \t \t e.printStackTrace(); \t \t} \t \t resultado de devolución; \t} Por encima del método, "java.lang.IllegalArgumentException: Key length not 128/160/192/224/256 bits." – Krish

+0

@Krish Acabo de agregar a la respuesta la implementación md5. –

Cuestiones relacionadas