AES (Advanced Encription Standard): Es un algoritmo de cifrado simétrico por bloques basado en el desarrollo de Joan Daemen y Vicent Rijmen bajo el nombre de Rijndael (pronunciado “Reindal” para los que no sean belgas), transformado en estándar en mayo de 2002.

Como funciona AES

Uniendo tres buenas ideas:

1.- Confusión: La primer idea es ocultar la relación entre el mensaje en texto claro y el mensaje cifrado. Un ejemplo es el viejo y conocido cifrado del César.

2.- Difusión: La segunda idea fue esparcir el mensaje original, en este caso aplicando una simple transposición de columnas.

3.- Sólo la clave es secreta: La tercer y última idea es asumir que el método en algún momento será conocido, y la fortaleza del cifrado estará apoyada solo en la clave.

El algoritmo se basa en varias sustituciones, permutaciones y transformaciones lineales ejecutadas en bloques de datos, repitiendo estas operaciones varias veces (o rondas) dependiendo de la longitud de la clave que puede ser de 128, 192 y 256 bits (llamado AES-128, AES-192 o AES-256 respectivamente).

Modo de Operación de AES

ECB: Electronic CodeBook, se dividen los mensajes en bloques y se cifran por separado utilizando la misma clave. La desventaja es que bloques de texto claro identico generan bloques identicos de texto cifrado. Es por eso que esta desaconsejado el uso de ECB.

CBC: Cipher-block Chaining, se agrega el IV o vector de inicialización, un código el cual aplicamos una operación XOR junto con el primer bloque en texto claro, se cifra con la clave como describe el algoritmo, y este primer bloque cifrado además será utilizado como el NUEVO IV para el siguiente bloque del mensaje. La desventaja es que el cifrado pasa a ser un proceso secuencial y por lo tanto no puede ser paralelizado.

PCBC: Propagating Cipher Block Chaining, opera de manera similar al método CBC con pequeña diferencia. Para obtener el NUEVO IV del siguiente bloque, lo que se se aplicara es una operación XOR sobre los bloques cifrados y en texto claro anteriores.

Los métodos descriptos hasta aquí operan estrictamente sobre bloques. Si el mensaje no tiene una longitud múltiplo del tamaño del bloque se le añadirá al último un relleno o padding para llegar a dicha longitud. Los algoritmos que describiremos a continuación se denominan de flujo o keystream, con la propiedad de poder soportar perdida de bloques tolerando algunos cortes en el flujo, lo que nos permite recuperar parte de la información sin la completitud del mensaje. Este tipo de cifrado se puede utilizar por ejemplo para transmisiones de audio o video.

CFB: Cipher feedback, es un pariente cercano del CBC, con la diferencia de que el bloque cifrado con la clave en este caso será el IV, el cual genera un IV CIFRADO que al cual se aplicará un XOR con el primer bloque de texto claro para obtener así el primer bloque de texto cifrado; quien a su vez se convertirá en el NUEVO IV, el cual será nuevamente cifrado para continuar el flujo del mensaje aplicando una vez mas una funcion XOR con el segundo bloque de texto claro, y así sucesivamente. Se puede observar que ahora si podríamos recuperar cualquier bloque de texto en claro siempre y cuando tengamos disponible el siguiente bloque cifrado y el bloque cifrado anterior (o el IV para el primer caso).

OFB: Output feedback, tiene una modificación en su función que permite independizarse del bloque de texto cifrado siguiente ya que lo que se convertirá en el NUEVO IV es el IV CIFRADO del bloque consecutivo sin la operación XOR que lo vincula con el bloque en texto claro. Para entenderlo mejor es conveniente observar el esquema de OFB_decryption

CTR: Counter, agrega al OFB un contador o número de secuencia que se combina con el IV (también llamado NONCE) para poder paralelizar la función de cifrado ahora independiente del bloque que se opere ya ahora se mantiene el número de orden del bloque.

Cifrando un texto con OpenSSL desde la línea de comandos

// Transformar el IV y la clave a Hexa
pablo@laptop: hexiv=$(echo -n '0000000000000000' | hexdump -v -e '/1 "%02X"')                 // -e Format String con un Hex Byte sin separadores
pablo@laptop: hexpass=$(echo -n 'mysecret' | hexdump -v -e '/1 "%02X"')                       // -e Format String con un Hex Byte sin separadores
pablo@laptop: echo -n '12345' | openssl enc -aes-256-cbc -iv "$hexiv" -K "$hexpass" -a -p     // -a para imprimir la salida en Base64.
salt=0000000000000000                                                                         // -p imprime los parámetros utilizados
key=6D79736563726574000000000000000000000000000000000000000000000000
iv =30303030303030303030303030303030
4HdSmrDa3s7Hc7+cTVMtHg==

Cifrando un texto con PHP desde la línea de comandos

pablo@laptop: php -r 'echo( openssl_encrypt ("12345", "aes-256-cbc","mysecret",false,"0000000000000000"));'           // KEY e IV en Text
4HdSmrDa3s7Hc7+cTVMtHg==

Cifrar y descifrar un texto con un Form y PHP

<html>
<head>
    <title>Aplicacion de Cifrado</title>
</head>
<body>
    <div align="center">
    <h1>AES-256</h1>
    <form method="POST">
        Clave: <input type="text" id="key" name="key" size=25><br>
        Texto: <input type="text" id="text" name="text" size=25><br>
        <?php
        $array = array("aes-256-cbc","aes-256-cfb","aes-256-ecb","aes-256-ofb");
        echo "<select id=\"meth\" name=\"meth\" style=\"display: none;\">\n";
        foreach ($array as $valor){
            echo "<option value=\"$valor\">$valor</option>\n";
        }
        echo "</select>";
        ?>
        <input type="radio" name="action" value="crypt" checked  onclick="getElementById('meth').style.display='none'">Cifrar
        <input type="radio" name="action" value="decrypt" onclick="getElementById('meth').style.display='block'">Descifrar<br>
        <input type="submit" value="Aceptar">
    </form>
    <?php
    if ($_POST["action"]=="crypt"){
    foreach ($array as $valor){
        $text = openssl_encrypt ($_POST["text"], $valor,$_POST["key"],false,"0000000000000000");
        echo "<b>" . strtoupper($valor) . ":</b> $text<br>";
    }
    }elseif ($_POST["action"]=="decrypt"){
        $text = openssl_decrypt ($_POST["text"], $_POST["meth"] ,$_POST["key"],false,"0000000000000000");
        echo "<b>Texto Claro:</b> $text";
    }
    ?>
    </div>
</body>
</html>

Referencias:
How to make openssl encrypt passwords like php via command line
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Feedback_(CFB)