Convertir encriptación en PHP 3DES en C#

Recientemente ha avisado que el sistema de pago por TPV virtual de Redsys se va a actualizar. En esta actualización se van a incorporar medidas de cifrado más potentes que la firma actual que se tiene implementado. Para ello los bancos han enviado cierta documentación (un poco tarde…) para hacer esta migración, puesto que el 23/11/2015 se supone que dejará de funcionar el sistema de encriptación actual.

Realizando la migración en mi empresa me he encontrado con un escollo que me ha costado un poco de solventar, y por lo que veo a muchos más desarrolladores de .NET les ha sucedido lo mismo. El problema está en el cifrado triple DES.

Este es el código de ejemplo que te facilitan en Redsys para realizar este cifrado.

function encrypt_3DES($message, $key){
// Se establece un IV por defecto
$bytes = array(0,0,0,0,0,0,0,0); //byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
$iv = implode(array_map("chr", $bytes)); //PHP 4 = 4.0.2


// Se cifra
$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); //PHP 4 >= 4.0.2
return $ciphertext;
}


$key = $this->decodeBase64($key);
$ciphertext = $this->encrypt_3DES($message, $key);

La variable $message sería el texto a encryptar (en el caso de Redsys el número de pedido). La variable $key es la clave de encriptación de Redsys que previamente la decodificamos en Base64.
Al final obtenemos un resultado ($ciphertext) que es un array de bytes.

Ahora viene cuando hacemos lo mismo en .NET C#.


///
/// Uso de la encriptación TripleDES con IV todo 0 -> byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
/// Esta encriptación se usa así para los TPV's de Redsys
///


///Texto a encriptar ///Clave de la encriptación en un array de Bytes ///
public static byte[] EncriptarTripleDES_IV_0(string texto, byte[] key)
{
using (TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider())
{
byte[] iv_0 = { 0, 0, 0, 0, 0, 0, 0, 0 };  //same IV that Redsys
byte[] toEncryptArray = Encoding.ASCII.GetBytes(texto);
tdes.IV = iv_0;
//assign the secret key
tdes.Key = key;
tdes.Mode = CipherMode.CBC;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = tdes.CreateEncryptor();
//transform the specified region of bytes array to resultArray
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,toEncryptArray.Length);
//Clear to Best Practices
tdes.Clear();
return resultArray;
}
}

Esta función nos devuelve el mismo resultado que la orginial proporcionada por Redsys en PHP.

Como utilizar una consulta PHP 2 veces



En PHP es posible que necesitemos usar una consulta 2 veces. Un ejemplo práctico de ésto, sería rellenar 2 combos con la misma consulta, sin tener que copiar los combos. La solución sería que tras recorrer el array de la consulta para cargar el primer combo, volver a poner el puntero de la consulta al primer registro de ésta. Esto se hace con “mysql_data_seek

Ejemplo:

$conexion=mysql_connect(DB_HOST,DB_USER,DB_PASSWORD);
if(!$conexion)
{
    echo "No se pudo conectar a la DB";
}else
{
	mysql_select_db(DB_NAME) or die ("No se puedo conectar con la base de datos");

	$resultado=mysql_query("SELECT equipo FROM equipos
                                WHERE categoria='PrimeraCategoria'",$conexion);

	if(!$resultado)
	{
		echo "La consulta no funciono";
	}else
        {
                //CARGO EL PRIMER COMBO
                echo '<label>Equipo Local:</label>';
                echo '<select style="width: 225px;" name="equipoLocal">';
                while ($row=mysql_fetch_row($resultado))
                {
                      echo'<option value="'.$row[0].'">'.$row[0].'</option>';
                }
                echo '</select>';

                //Devuelvo al array de la consulta a la posición de partida para volverlo a recorrer
               if( !mysql_data_seek($resultado, 0) )
               {
                      die( "No se pudo regresar al primer resultado" );
               }else
               {      //CARGO EL SEGUNDO COMBO
                      echo '<label>Equipo Visitante:</label><br>';
                      echo '<select name= "equipoVisitante" style="width: 225px">';
                      while ($row=mysql_fetch_row($resultado))
                      {
                            echo'<OPTION VALUE="'.$row[0].'">'.$row[0].'</OPTION>';
                      }
                      echo '</select>';
               }
       }
}

Como ocultar la versión de PHP de peticiones remotas en Apache

logotipo de php

Tal vez nos interese ocultar la versión de PHP en nuestro servidor Apache para las peticiones remotas. Es decir que PHP no agrege su firma (signature) a las cabeceras (header) del servidor web. Con esto conseguiríamos que sea mucho más dificil averiguar la versión que utilizamos en nuestro servidor, y con eso evitar que sea fácil aprovechar las vulnerabilidades de la versión de PHP que utilicemos.

Con este tutorial evitaremos esa información:

1. Localiza el archivo php.ini. Dependiendo de tu sistema, este archivo puede estar en rutas como estas:

/etc/php.ini
/usr/bin/php.ini
/usr/local/bin/php.ini
/etc/php5/apache2/php.ini

si no sabes dónde se encuentra el archivo, usa este comando:

locate php.ini

2. Abre el archivo y localiza esta línea:

expose_php On

3. Cambialó por:

expose_php = Off

Sal y guarda el archivo:

4. Reinicia el servidor Apache para que te tome este cambio.

sudo /etc/init.d/apache2 restart

ó:

sudo /etc/init.d/apache2 stop
sudo /etc/init.d/apache2 start

Como poner comentarios en PHP

logotipo de php

Es muy útil en programación comentar trozos de código, o poner aclaraciones o comentarios sobre el mismo, para hacerlo en PHP sirven cualquiera de estas formas:

<?
este código se ejecutaría
// esto no se ejecutaría

/* esto tampoco se

ejecutaría */
?>

También se puede usar la “almoadilla” ‘#’
<?
# esto no se ejecutaría
este código se ejecutaría
?>

Si pones un comentario dentro de otro no te funcionará

<?
/* /* No funcionará */ */
?>