Pregunta

He pasado un par de horas ahora tratando de resolver esto, pero simplemente no puede conseguir que funcione. Tengo una rutina de cifrado en C # que tenemos que asociar en php. No puedo cambiar la versión de C #, que no es una opción (tercera parte es firme en esto).

Este es el código C #:

//In C#
// Console.WriteLine(ApiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl"));
// Results in: 
//     XvHbR/CsLTo=
public static string ApiEncode(string data, string secret)
{
  byte[] clear;

  var encoding = new UTF8Encoding();
  var md5 = new MD5CryptoServiceProvider();

  byte[] key = md5.ComputeHash(encoding.GetBytes(secret));

  TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
  des.Key = key;
  des.Mode = CipherMode.ECB;
  des.Padding = PaddingMode.PKCS7;

  byte[] input = encoding.GetBytes(data);
  try { clear = des.CreateEncryptor().TransformFinalBlock(input, 0, input.Length); }
  finally
  {
    des.Clear();
    md5.Clear();
  }

  return Convert.ToBase64String(clear);
}

Aquí está lo mejor de lo que yo he llegado con en PHP:

//In PHP
// echo apiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl");
// Results in: 
//    5aqvY6q1T54=
function apiEncode($data, $secret)
{    
  //Generate a key from a hash
  $key = md5(utf8_encode($secret), true);
  //Create init vector  
  $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ecb), MCRYPT_RAND); 

  //Pad for PKCS7
  $blockSize = mcrypt_get_block_size('tripledes', 'ecb');
  $len = strlen($data);
  $pad = $blockSize - ($len % $blockSize);
  $data .= str_repeat(chr($pad), $pad);

  //Encrypt data
  $encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); //, $iv);
  return base64_encode($encData);
}

A lo mejor de mi conocimiento, yo estoy manejando el relleno PKCS7 adecuadamente en el lado de PHP. No estoy seguro de qué más probar.

Una cosa a la nota, el C # está sucediendo en las ventanas, y el PHP en Linux, no estoy seguro de que debe hacer una diferencia.

¿Fue útil?

Solución

La longitud de relleno en su versión de PHP se basa en la longitud de la contraseña. Esto es incorrecto. Debe basarse en la duración de su mensaje en su lugar.

Trate de reemplazar strlen($password) con strlen($data).


El segundo problema es que la biblioteca mcrypt requiere claves de 24 bytes. Triple DES se aplica regulares DES tres veces, para que pueda llamar la clave de 8 bytes utilizado en cada ronda de DES K 1 , K 2 , y K 3 . Hay diferentes maneras de elegir estas teclas. El más seguro es elegir tres claves distintas. Otra forma es configurar K 3 igual a k 1 . El método menos seguro (equivalente a DES) es hacer que K 1 = K 2 = K 3 .

La mayoría de las bibliotecas son suficientemente "inteligentes" para interpretar una clave 3DES de 16 bytes como la segunda opción anterior: K 3 = K 1 . La aplicación .NET está haciendo esto para usted, pero la biblioteca mcrypt no lo es; En cambio, es el establecimiento de K 3 = 0. Tendrá que solucionar este problema usted mismo, y pasar mcrypt una clave de 24 bytes.

Después de calcular el hash MD5, dar los primeros 8 bytes de $key, y los añade al final de $key, para que tenga un valor de 24 bytes para pasar a mcrypt_encrypt().

Otros consejos

He encontrado una solución, compruebe este enlace, puede ayudarle. http://sanity-free.com/131/triple_des_between_php_and_csharp.html

Y aquí es la función de descifrado por si acaso:

    public static string Decrypt(string cypherString)
    {

        byte[] key = Encoding.ASCII.GetBytes("icatalogDR0wSS@P6660juht");
        byte[] iv = Encoding.ASCII.GetBytes("iCatalog");
        byte[] data = Convert.FromBase64String(cypherString);
        byte[] enc = new byte[0];
        TripleDES tdes = TripleDES.Create();
        tdes.IV = iv;
        tdes.Key = key;
        tdes.Mode = CipherMode.CBC;
        tdes.Padding = PaddingMode.Zeros;
        ICryptoTransform ict = tdes.CreateDecryptor();
        enc = ict.TransformFinalBlock(data, 0, data.Length);
        return UTF8Encoding.UTF8.GetString(enc, 0, enc.Length);
    }

Tome un vistazo a encoding.getBytes, necesita los secretos Bytes clave de UTF8 ...

Aparece la versión de C # no establece el IV . Esto podría ser un problema si usted no sabe lo que es porque MSDN dice:

La propiedad IV se establece automáticamente en un nuevo valor aleatorio cada vez que se crea una nueva instancia de una de las clases SymmetricAlgorithm o cuando se llama al método manual GenerateIV.

Parece que en la versión de PHP, está utilizando un IV . Se podría tratar de no suministrar la IV y la esperanza de la versión C # también utiliza ceros.

Edit:. Ve como para BCE, el IV es ignorado

También podría tener que codifica la clave, como en la versión # C utilizando utf8- codificar

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top