2011-12-16 46 views
6

Estoy tratando de descifrar una clave cifrada por la función Triple DES de Java utilizando la función PHP mcrypt pero sin suerte. Encuentra debajo del código de JavaPHP Equivalente para Java Triple cifrado/descifrado DES

import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 


public class Encrypt3DES { 

    private byte[] key; 
    private byte[] initializationVector; 

    public Encrypt3DES(){ 

    } 

    public String encryptText(String plainText, String key) throws Exception{ 

     //---- Use specified 3DES key and IV from other source -------------- 
     byte[] plaintext = plainText.getBytes(); 
     byte[] myIV = key.getBytes(); 
     byte[] tdesKeyData = {(byte)0xA2, (byte)0x15, (byte)0x37, (byte)0x08, (byte)0xCA, (byte)0x62, 
     (byte)0xC1, (byte)0xD2, (byte)0xF7, (byte)0xF1, (byte)0x93, (byte)0xDF, 
     (byte)0xD2, (byte)0x15, (byte)0x4F, (byte)0x79, (byte)0x06, (byte)0x67, 
     (byte)0x7A, (byte)0x82, (byte)0x94, (byte)0x16, (byte)0x32, (byte)0x95}; 

     Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
     SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede"); 
     IvParameterSpec ivspec = new IvParameterSpec(myIV); 
      c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec); 
     byte[] cipherText = c3des.doFinal(plaintext); 
     sun.misc.BASE64Encoder obj64=new sun.misc.BASE64Encoder(); 
     return obj64.encode(cipherText); 

    } 

    public String decryptText(String encryptText, String key) throws Exception{ 


     byte[] initializationVector = key.getBytes(); 
     byte[] tdesKeyData = {(byte)0xA2, (byte)0x15, (byte)0x37, (byte)0x08, (byte)0xCA, (byte)0x62, 
     (byte)0xC1, (byte)0xD2, (byte)0xF7, (byte)0xF1, (byte)0x93, (byte)0xDF, 
     (byte)0xD2, (byte)0x15, (byte)0x4F, (byte)0x79, (byte)0x06, (byte)0x67, 
     (byte)0x7A, (byte)0x82, (byte)0x94, (byte)0x16, (byte)0x32, (byte)0x95}; 


      byte[] encData = new sun.misc.BASE64Decoder().decodeBuffer(encryptText); 
      Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
      SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede"); 
      IvParameterSpec ivspec = new IvParameterSpec(initializationVector); 
      decipher.init(Cipher.DECRYPT_MODE, myKey, ivspec); 
      byte[] plainText = decipher.doFinal(encData); 
      return new String(plainText); 

    } 
} 

Quiero escribir una función PHP equivalente a la función de Java decryptText anteriormente. Estoy encontrando dificultades para generar el valor de IV exacto generado por el código de Java para el cifrado, que es necesario para el descifrado.

+0

Tema relacionado - http://stackoverflow.com/questions/20227/how-do-i-use-3des-encryption-decryption-in-java – adatapost

Respuesta

9

Este es el PHP equivalente del código Java (he copiado el archivo PKCS # 5-padding del comentario 20-Sep-2006 07:56 de The mcrypt reference)

function encryptText($plainText, $key) { 
    $keyData = "\xA2\x15\x37\x08\xCA\x62\xC1\xD2" 
     . "\xF7\xF1\x93\xDF\xD2\x15\x4F\x79\x06" 
     . "\x67\x7A\x82\x94\x16\x32\x95"; 

    $padded = pkcs5_pad($plainText, 
     mcrypt_get_block_size("tripledes", "cbc")); 

    $encText = mcrypt_encrypt("tripledes", $keyData, $padded, "cbc", $key); 

    return base64_encode($encText); 
} 

function decryptText($encryptText, $key) { 
    $keyData = "\xA2\x15\x37\x08\xCA\x62\xC1\xD2" 
     . "\xF7\xF1\x93\xDF\xD2\x15\x4F\x79\x06" 
     . "\x67\x7A\x82\x94\x16\x32\x95"; 

    $cipherText = base64_decode($encryptText); 

    $res = mcrypt_decrypt("tripledes", $keyData, $cipherText, "cbc", $key); 

    $resUnpadded = pkcs5_unpad($res); 

    return $resUnpadded; 
} 


function pkcs5_pad ($text, $blocksize) 
{ 
    $pad = $blocksize - (strlen($text) % $blocksize); 
    return $text . str_repeat(chr($pad), $pad); 
} 

function pkcs5_unpad($text) 
{ 
    $pad = ord($text{strlen($text)-1}); 
    if ($pad > strlen($text)) return false; 
    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false; 
    return substr($text, 0, -1 * $pad); 
} 

Pero hay algunos problemas que se deben tener en cuenta:

  • En su código Java, llame al String.getBytes() sin indicar una codificación. Esto hace que su código no sea portátil si su texto no contiene caracteres ASCII como diéresis, porque Java usa el juego de caracteres predeterminado del sistema. Si puedes cambiar eso ciertamente lo haría. Te recomiendo usar utf-8 en ambos lados (Java y PHP).
  • Ha codificado duro la clave de cifrado y utiliza IV como "clave". De ninguna manera soy un experto en criptografía, pero para mí solo se siente mal y puede provocar una gran fuga de seguridad.
  • Crea un IV aleatorio y concatenalo al principio o al final de tu mensaje. Dado que el tamaño de IV es AFAIK igual al tamaño de bloque de su cifrado, simplemente elimina la cantidad de bytes del inicio o del final y separa fácilmente el IV del mensaje.
  • En cuanto a la clave, es mejor utilizar algún tipo de método key derivation para generar una clave con el tamaño correcto a partir de una contraseña "generada por el ser humano".

Por supuesto, si debe cumplir algunos requisitos, no puede cambiar su método.

+0

gracias mucho vstm. Voy a verificar y revertir. – Ranju

+0

¡funciona muy bien! ¡mil gracias por tu ayuda! – Ranju

+0

Puedo cambiar el valor de una variable $ keyData? –

0

¡La respuesta es casi buena! Sólo revertir $keyData y $key en

$encText = mcrypt_encrypt("tripledes", $keyData, $padded, "cbc", $key); 

y

$res = mcrypt_decrypt("tripledes", $keyData, $cipherText, "cbc", $key); 

lo contrario, siempre va a utilizar la misma clave 3DES. Y es mejor cambiar el nombre de $keyData a $iv.

De todos modos, muchas gracias por la muestra de Java y la traducción Php-Java.