Archivo

Entradas Etiquetadas ‘mensaje’

Recopilación de soluciones para los retos de #tuentiContest . Challenge #19

Jueves, 30 de Junio de 2011 Gaspar Fernández Sin comentarios

Últimamente he hablado acerca del I concurso de programación de Tuenti. Un concurso de programación Online que se llevó acabo durante la semana pasada (del 13 al 20 de Junio, muy mala fecha).

Podéis ver los enunciados de todos los problemas, con ejemplos sobre la entrada y salida (aunque a veces no hay que hacerles mucho caso) en la web oficial del concurso, pero en Vidas Concurrentes lo encontramos todo en español.

Challenge #19 : The Caesar Salad

Un mensaje cifrado con 4 métodos distintos, todo acompañado de una adivinanza
Soluciones:

Si no estás en la lista y quieres plantear tu solución, deja un comentario con tu link !

Actualización 2011/07/03 01:49 : Añadida solución de @frisco82
Actualización 2011/07/03 13:52 : Añadida solución de @Rosapolis

Esteganografía: Inserción en el LSB en PHP (Solucionando el Challenge 17 en #tuentiContest)

Miércoles, 29 de Junio de 2011 Gaspar Fernández Sin comentarios

La esteganografía es el arte de introducir una información dentro de otra de forma oculta, ya sea texto dentro de imagen, audio dentro de imagen, imagen dentro de audio, imagen dentro de imagen, lo que nos dé la imaginación.

Hace unos meses, en Código para llevar leí un par de posts interesantes sobre este tema, donde se proponía una implementación en Python ( I y II )

En este caso, se trata de descifrar un texto oculto dentro de una imagen PNG. ¿ Por qué PNG ? Sobre todo porque es un estándar bastante extendido de compresión de imágenes sin pérdidas, podría ser también un JPEG LS, aunque se ve menos.
La técnica utilizada para “ocultar” el mensaje se basa en modificar el bit menos significativo de cada componente de cada pixel de la imagen, y es que para el ojo humano, en una gama de 256 niveles de rojo, por ejemplo, le resulta muy pero que muy difícil (por no decir imposible), distinguir entre dos niveles muy próximos, así que nos aprovechamos de eso, utilizaremos el bit menos significativo (LSB) de cada componente para escribir nuestro mensaje, y a efectos prácticos no nos daremos cuenta visualmente de esto. Además, podremos encerrar un carácter ASCII por cada 2.66 pixels (3componentes por pixel, 8 bits por carácter).

En el reto, el mensaje estaba encerrado sólo en la primera línea de la imagen, por lo que sólo leeremos esa línea, es fácil extender el código a varias líneas o columnas, incluso.

Vamos a por un poco de código de cómo descifrar el mensaje:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
// Esta función cogerá las componentes RGB del pixel situado en
// $x, $y
function getcolor($img, $x, $y)
{
  $rgb = imagecolorat($img, $x, $y);
  $r = ($rgb >> 16) & 0xFF;
  $g = ($rgb >> 8) & 0xFF;
  $b = $rgb & 0xFF;
 
  return array($r, $g, $b);
}

// Convierte una cadena de unos y ceros a ASCII, cogiendo de 8 en 8
function _bin2asc($str)
{
  $len = strlen($str);
 
  for ($i=0;$i<$len;$i+=8)
  {
    $ch=bindec(substr($str,$i,8));
    $data[]=$ch;
  }
  return $data;
}

// Extrae los datos de los LSB de cada componente
function decod($i)
{
  $tx=imagesx($i);
  $ty=imagesy($i);
  // Eliminar la línea de abajo para extraer información de toda la imagen
  $ty=1;

  $data='';
  for ($y=0; $y<$ty; $y++)
    {
      for ($x=0; $x<$tx; $x++)
    {
      $cdat=getcolor($i, $x, $y);

      $data.=($cdat[0]&1).($cdat[1]&1).($cdat[2]&1);
    }
    }
  return $data;
}

$img=imagecreatefrompng($tnam);

$d=decod ($img);
echo $d;
?>

Es cierto que esto habría que optimizarlo mucho, ya que estamos almacenando valores binarios en una cadena, ocuparía mucho y tardaríamos tiempo en la reconstrucción ya que _bin2asc() trabaja haciendo contantemente substr(). Podríamos por ejemplo reconstruir el mensaje a medida que vamos obteniendo bits, almacenando en un buffer hasta 8 bits. Aunque yo creo que este ejemplo se entiende mejor, y por otra parte, dada la naturaleza del concurso había que investigar muchas posibilidades, por lo que era mejor hacer un código menos óptimo y más rápido de hacer.

Por otra parte, para solucionar el reto del #tuentiContest, era importante colocar los bits en orden, es decir, los bits extraídos no están es este orden, teníamos que investigar y hacer pruebas, en lugar de estar en RGB (como en el ejemplo superior), están en BGR.

A continuación, aunque no era necesario para el reto, incluyo mi solución, un programa que extrae la información de la entrada estándar, la decodifica (base64_decode), la pasa a un archivo PNG y abrimos ese archivo desde PHP que leeremos. A continuación teníamos que devolver un fragmento del código extraído, por lo tanto delimitamos el texto y devolvemos. Aunque sólo bastaba con hacer un programa que escribiera el código.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
// Convierte una cadena de unos y ceros a ASCII, cogiendo de 8 en 8
function _bin2asc($str)
{
  $len = strlen($str);
 
  for ($i=0;$i<$len;$i+=8){
    $ch=bindec(substr($str,$i,8));

      $data[]=$ch;

  }
  return $data;
}

function decod($i)
{
  $tx=imagesx($i);
  $ty=imagesy($i);

  $ty=1;

  $data='';
  for ($y=0; $y<$ty; $y++)
    {
      for ($x=0; $x<$tx; $x++)
    {
      $cdat=getcolor($i, $x, $y);

      $data.=($cdat[2]&1).($cdat[1]&1).($cdat[0]&1);
    }
    }
  return $data;
}

// Esta función cogerá las componentes RGB del pixel situado en
// $x, $y
function getcolor($img, $x, $y)
{
  $rgb = imagecolorat($img, $x, $y);
  $r = ($rgb >> 16) & 0xFF;
  $g = ($rgb >> 8) & 0xFF;
  $b = $rgb & 0xFF;
 
  return array($r, $g, $b);
}

$fp=fopen("php://stdin","r");

$line='';
while(!feof($fp))
  {
    $line.=fread($fp,5192);
  }

$tnam=tempnam("/tmp", "tuenticontest_");
file_put_contents($tnam, base64_decode($line));
$img=imagecreatefrompng($tnam);

$d=decod ($img);

$b=_bin2asc($d);

$frase='';
for ($i=0; $i<count($b); $i++)
  $frase.=chr($b[$i]);
//echo $frase;
$pre='following code: ';
$code=substr($frase, strpos($frase,$pre)+strlen($pre));
$clean=substr($code, 0, strpos($code, '.'));
echo $clean;

?>

Intercalar 2 ó más cadenas en PHP

Lunes, 9 de Agosto de 2010 Gaspar Fernández Sin comentarios

A la hora de crear un hash para una contraseña, es conveniente no incluir sólo la contraseña, sino concatenar una cadena o un número más; lo mismo cuando generamos claves para que interaccionen aplicaciones en varios servidores; aunque hay veces en que, dados los pocos datos de que disponemos a la hora de generar la clave, no tenemos mucho donde elegir a la hora de crear el hash.

Por ese motivo se me ocurrió esta función en PHP, lo que hace es intercalar cadenas, es decir, tenemos dos cadenas, y queremos generar una cadena a partir de las dos anteriores, podemos coger un carácter de una, otro de otra, y así sucesivamente (como si estuviéramos barajando) hasta formar una cadena cuya longitud es la suma de las dos. Por ejemplo si tenemos las palabras “poesia” y “binaria“, resultaría la cadena: pboiensairaia .

Aunque, ya que vamos a hacer algo así, ¿ por qué limitarlo ? Hagamos una función que soporte una cantidad indeterminada de cadenas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function intercalar($cadenas)
{
  $n_cadenas = count ($cadenas);

  if ($n_cadenas==1)        /* Si sólo hay una cadena, la devolvemos */
    return $cadenas[0];

  /* Contamos los caracteres de cada cadena y los almacenamos en un array */
  $chars_cadena=array();
  for ($i=0; $i<$n_cadenas; $i++)
    $chars_cadena[$i]=strlen($cadenas[$i]);

  $max_cadena = max ($chars_cadena); /* La cadena más larga determina cuándo paramos */
  $res='';
  /* Recorremos la longitud de cadena más larga */
  for ($j=0; $j<$max_cadena; $j++)
    {
      /* Recorremos todas las cadenas */
      for ($i=0; $i<$n_cadenas; $i++)
    {
      /* Si la cadena no está terminada añadiremos el carácter a la cadena */
      if ($j<$chars_cadena[$i])
        $res.=$cadenas[$i][$j];
    }
    }

  return $res;
}

echo intercalar (array("Poesia", "Binaria", "Blog", "Gaspar", "Programacion", "Software", "Libre"));

La cadena resultante de este ejemplo será: PBBGPSLoilaroienosofbsagpgtrirarweairaaamraecion.

Visita otras webs de la red