Diferencia entre el cifrado .NET y PHP

Tengo el siguiente código C# que genera claves:

    public static byte[] Encrypt(byte[] plainData, string salt)
    {
        DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
        DES.Key = ASCIIEncoding.ASCII.GetBytes(salt);
        DES.IV = ASCIIEncoding.ASCII.GetBytes(salt);
        ICryptoTransform desencrypt = DES.CreateEncryptor();
        byte[] encryptedData = desencrypt.TransformFinalBlock(plainData, 0, plainData.Length);
        return encryptedData;
    }

    private string GetEncryptedKey(string key)
    {
        return BitConverter.ToString(KeyGeneratorForm.Encrypt(ASCIIEncoding.ASCII.GetBytes(key), "abcdefgh")).Replace("-", "");
    }

Estoy tratando de hacer lo mismo en PHP:

function get_encrypted_key($key){
    $salt = "abcdefgh";
    return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}

Sin embargo, existe una pequeña discrepancia en los resultados, ya que los últimos 16 caracteres siempre son diferentes:

With key "Benjamin Franklin":
C# : 0B3C6E5DF5D747FB3C50DE952FECE3999768F35B890BC391
PHP: 0B3C6E5DF5D747FB3C50DE952FECE3993A881F9AF348C64D

With key "President Franklin D Roosevelt":
C# : C119B50A5A7F8C905A86A43F5694B4D7DD1E8D0577F1CEB32A86FABCEA5711E1
PHP: C119B50A5A7F8C905A86A43F5694B4D7DD1E8D0577F1CEB37ACBE60BB1D21F3F

También intenté realizar la transformación de relleno en mi clave usando el siguiente código:

function get_encrypted_key($key){
    $salt = "abcdefgh";

    $extra = 8 - (strlen($key) % 8);
    if($extra > 0) {
        for($i = 0; $i < $extra; $i++) {
            $key.= "\0";
        }
    }

    return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}

Pero termino con los mismos resultados que sin relleno.

Si tienes alguna idea de lo que está pasando, ¡me encantaría saberlo! :)

Muchas Gracias

preguntado el 12 de junio de 12 a las 21:06

¿Quizás como resultado de diferentes esquemas de relleno? -

Si por fragmento de relleno "clásico" se refiere al que se menciona justo en la parte superior de las notas en mcrypt_encrypt, que me da tu C# resultados de PHP. Tenga en cuenta que el fragmento usa ECB, no CBC, por lo que debe modificarlo. -

Gracias por vuestros comentarios chicos. He detallado el código que usé para el relleno. Buscaré el enlace de John. -

¿Qué tal tirarlo todo junto y reemplazarlo con algo que no apesta? -

@CodeInChaos ¿Qué agregaría a la respuesta correcta dada? -

1 Respuestas

Mencionaste probar un fragmento de relleno "clásico". La siguiente adaptación rápida del fragmento publicado en el mcrypt_encrypt documentación da los mismos resultados que estaba obteniendo de C#.

PKCS #7 (el esquema de relleno predeterminado utilizado por C# SymmetricAlgorithm) rellenos con bytes donde el valor de cada byte de relleno es el mismo que el número de bytes de relleno, no con cero bytes.

function get_encrypted_key($key)
{
    $salt = 'abcdefgh';
    $block = mcrypt_get_block_size('des', 'cbc');
    $pad = $block - (strlen($key) % $block);
    $key .= str_repeat(chr($pad), $pad);

    return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}

Salida de prueba:

php > echo get_encrypted_key('Benjamin Franklin');
0b3c6e5df5d747fb3c50de952fece3999768f35b890bc391
php > echo get_encrypted_key('President Franklin D Roosevelt');
c119b50a5a7f8c905a86a43f5694b4d7dd1e8d0577f1ceb32a86fabcea5711e1

Respondido el 12 de junio de 12 a las 22:06

Muchas gracias John, eso es perfecto. koni

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.