• Publicidad

Error raro en script cifrado y descifrado Vigenère

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Error raro en script cifrado y descifrado Vigenère

Notapor otronovato » 2013-08-28 16:20 @722

Un saludo a todos. Me he pasado la tarde haciendo un script para cifrar y descifrar mediante el método Vigenère. Me interesa sobre todo porque quería empezar a trabajar con estructuras un poco más complejas que un simple array.

El script es éste:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #Programa de cifrado Vigenère
  3.  
  4. use strict;
  5. use warnings;
  6. use utf8::all;
  7.  
  8. #Creamos la matriz 27 x 27 de Vigenère mediante un array de referencias a otros arrays
  9.  
  10. my @alfa = ('A'..'N','Ñ','O'..'Z');
  11. my @num = (0..26);
  12. my %contacto;
  13. @contacto{@alfa}=@num;
  14. my @vigenere = (['A'..'N','Ñ','O'..'Z']);
  15. my $cont;
  16. my $cont2;
  17. my $fila;
  18. my $col;
  19. my @cifra;
  20. my @descifrado;
  21.  
  22. for($cont=1;$cont<=26;$cont++){
  23.  
  24.     for($cont2=0;$cont2<=26;$cont2++){
  25.         $vigenere[$cont]->[$cont2] = $vigenere[$cont-1]->[$cont2];
  26.     }
  27.         my $prim_car = shift $vigenere[$cont];
  28.         push $vigenere[$cont], $prim_car;
  29. }
  30.  
  31. #Comprobamos que la matriz está correctamente poblada
  32. for($fila=0;$fila<=$#vigenere;$fila++){
  33.  
  34.     print "\n";
  35.  
  36.     for($col=0;$col<=26;$col++){
  37.  
  38.         print $vigenere[$fila]->[$col];
  39.     }
  40. }
  41.  
  42. print "\n";
  43.  
  44. #Recogemos la clave y el mensaje de la línea de comandos
  45. #Suponemos que se trata de una cadena de mayúsculas sin espacios en blanco
  46.  
  47. my @clave = split //,$ARGV[0];
  48. my @mensaje = split //, $ARGV[1];
  49.  
  50. #Extendemos la clave hasta el tamaño del mensaje  
  51. my @clave_ext;
  52.  
  53. for(my $ind = 0;$ind <= $#mensaje;$ind++){
  54.  
  55.     ($ind <= $#clave) ? ($clave_ext[$ind]=$clave[$ind]):($clave_ext[$ind] = $clave[($ind % $#clave)-1]);
  56. }
  57.  
  58. print "La clave es ", join '',@clave, "\n";
  59. print "La clave extendida es ", join '', @clave_ext, "\n";
  60. print "El mensaje es ", join '', @mensaje, "\n";
  61.  
  62. #Algoritmo de vigenere propiamente dicho
  63.  
  64. for(my $cnt = 0;$cnt<= $#mensaje;$cnt++){
  65.  
  66.     my $car = $mensaje[$cnt];
  67.     my $key = $clave_ext[$cnt];
  68.  
  69. #Busco la fila de @vigenere que concuerde con $key gracias al hash %contacto.
  70.  
  71.     my $fil = $contacto{$key};
  72.  
  73. #Extraemos la columna de @vigenere que concuerda con el carácter de mensaje.
  74.  
  75.     my $colum = $contacto{$car};
  76.  
  77.     print $car, "\t", $key, "\t", $fil, "\t", $colum,"\n";
  78.  
  79. #Extraemos el valor correspondiente y lo introducimos en @cifra.
  80.  
  81.     push @cifra, $vigenere[$fil]->[$colum];
  82. }
  83.  
  84. print @cifra, "\n";
  85.  
  86. #Desciframos el mensaje
  87.  
  88. for(my $cnt2 = 0;$cnt2<=$#cifra;$cnt2++){
  89.  
  90.     my $columna;
  91.     my $car = $cifra[$cnt2];
  92.     my $key = $clave_ext[$cnt2];
  93.  
  94.  
  95.     my $fil = $contacto{$key};
  96.  
  97.     for(my $cnt3=0;$cnt3<=26;$cnt3++){
  98.  
  99.         if($car eq $vigenere[$fil]->[$cnt3]){
  100.  
  101.             $columna = $cnt3;
  102.         }
  103.  
  104.     }
  105.  
  106.     push @descifrado, $vigenere[0]->[$columna];
  107. }
  108.  
  109. print "El mensaje era \t", @descifrado, "\n";
  110.  
  111.  
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


El resultado es el siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
  1. xxxxx@xxxxx:~/Escritorio/scripts_criptografía$ ./vigenere.pl ABCDEF LAHERMOSAYGRACIOSANIÑAMARCHOSEALAVARLAROPA 
  2.  
  3. ABCDEFGHIJKLMNÑOPQRSTUVWXYZ 
  4. BCDEFGHIJKLMNÑOPQRSTUVWXYZA 
  5. CDEFGHIJKLMNÑOPQRSTUVWXYZAB 
  6. DEFGHIJKLMNÑOPQRSTUVWXYZABC 
  7. EFGHIJKLMNÑOPQRSTUVWXYZABCD 
  8. FGHIJKLMNÑOPQRSTUVWXYZABCDE 
  9. GHIJKLMNÑOPQRSTUVWXYZABCDEF 
  10. HIJKLMNÑOPQRSTUVWXYZABCDEFG 
  11. IJKLMNÑOPQRSTUVWXYZABCDEFGH 
  12. JKLMNÑOPQRSTUVWXYZABCDEFGHI 
  13. KLMNÑOPQRSTUVWXYZABCDEFGHIJ 
  14. LMNÑOPQRSTUVWXYZABCDEFGHIJK 
  15. MNÑOPQRSTUVWXYZABCDEFGHIJKL 
  16. NÑOPQRSTUVWXYZABCDEFGHIJKLM 
  17. ÑOPQRSTUVWXYZABCDEFGHIJKLMN 
  18. OPQRSTUVWXYZABCDEFGHIJKLMNÑ 
  19. PQRSTUVWXYZABCDEFGHIJKLMNÑO 
  20. QRSTUVWXYZABCDEFGHIJKLMNÑOP 
  21. RSTUVWXYZABCDEFGHIJKLMNÑOPQ 
  22. STUVWXYZABCDEFGHIJKLMNÑOPQR 
  23. TUVWXYZABCDEFGHIJKLMNÑOPQRS 
  24. UVWXYZABCDEFGHIJKLMNÑOPQRST 
  25. VWXYZABCDEFGHIJKLMNÑOPQRSTU 
  26. WXYZABCDEFGHIJKLMNÑOPQRSTUV 
  27. XYZABCDEFGHIJKLMNÑOPQRSTUVW 
  28. YZABCDEFGHIJKLMNÑOPQRSTUVWX 
  29. ZABCDEFGHIJKLMNÑOPQRSTUVWXY 
  30. La clave es ABCDEF 
  31. La clave extendida es ABCDEFABCDFABCDFABCDFABCDFABCDFABCDFABCDFA 
  32. El mensaje es LAHERMOSAYGRACIOSANIÑAMARCHOSEALAVARLAROPA 
  33. L    A    0    11 
  34. A    B    1    0 
  35. H    C    2    7 
  36. E    D    3    4 
  37. R    E    4    18 
  38. M    F    5    12 
  39. O    A    0    15 
  40. S    B    1    19 
  41. A    C    2    0 
  42. Y    D    3    25 
  43. G    F    5    6 
  44. R    A    0    18 
  45. A    B    1    0 
  46. C    C    2    2 
  47. I    D    3    8 
  48. O    F    5    15 
  49. S    A    0    19 
  50. A    B    1    0 
  51. N    C    2    13 
  52. I    D    3    8 
  53. Ñ    F    5    14 
  54. A    A    0    0 
  55. M    B    1    12 
  56. A    C    2    0 
  57. R    D    3    18 
  58. C    F    5    2 
  59. H    A    0    7 
  60. O    B    1    15 
  61. S    C    2    19 
  62. E    D    3    4 
  63. A    F    5    0 
  64. L    A    0    11 
  65. A    B    1    0 
  66. V    C    2    22 
  67. A    D    3    0 
  68. R    F    5    18 
  69. L    A    0    11 
  70. A    B    1    0 
  71. R    C    2    18 
  72. O    D    3    15 
  73. P    F    5    16 
  74. A    A    0    0 
  75. LBJHVQOTCBLRBELTSBOLSANCUHHPUHFLBXDWLBTRUA 
  76. El mensaje era     LAHERMOSAYGRACIOSANIÑAMARCHOSEALAVARLAROPA 


Pero... para que funcione he tenido que hacer una pequeña trampa. Concretamente, en la parte del programa que descifra el mensaje he tenido que poner "hardcoded" el valor de control del contador "26":

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.  for(my $cnt3=0;$cnt3<=26;$cnt3++){
  2.  
  3.         if($car eq $vigenere[$fil]->[$cnt3]){
  4.  
  5.             $columna = $cnt3;
  6.         }
  7.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En efecto, si intento usar como control $#cifra, como hago en el bucle anterior, obtengo el resultado correcto, pero también una avalancha de warnings:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. Use of uninitialized value in string eq at ./vigenere.pl line 100. 


¿Qué pasa aquí? No puede ser un tema de "scope" de la variable porque ha sido declarada en el bloque principal. Ni idea, vamos.

Por otro lado, respecto al código que afronta el descifrado, he leído en la red sobre un operador ~~ "smart smatching", pero no he logrado hacerme una idea de cómo utilizarlo. La tarea que necesito es establecer el índice del array @vigenere que cuadra con el valor de clave que le paso en la condición. ¿Alguna idea?

Ya puestos, no he encontrado otra forma de acceder a las listas que componen @vigenere sino elemento a elemento de cada lista. ¿Cómo se accede a cada elemento del array, (cada lista), en bloque?

Un saludo y muchas gracias
Última edición por otronovato el 2013-08-28 17:37 @776, editado 3 veces en total
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Publicidad

Re: Error raro en script cifrado y descifrado Vigenère

Notapor explorer » 2013-08-28 17:01 @751

otronovato escribiste:Me interesa sobre todo porque quería empezar a trabajar con estructuras un poco más complejas que un simple array.
Tienes una introducción a las estructuras complejas en el documento perllol.

otronovato escribiste:Pero... para que funcione he tenido que hacer una pequeña trampa. Concretamente, en la parte del programa que descifra el mensaje he tenido que poner "hardcoded" el valor de control del contador "26":

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.  for(my $cnt3=0;$cnt3<=26;$cnt3++){
  2.  
  3.         if($car eq $vigenere[$fil]->[$cnt3]){
  4.  
  5.             $columna = $cnt3;
  6.         }
  7.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En efecto, si intento usar como control $#cifra, como hago en el bucle anterior, obtengo el resultado correcto, pero también una avalancha de warnings

¿Qué pasa aquí?
Humm... @cifra guarda el cifrado del mensaje, según lo indica el bucle de las líneas 64-82... mientras que la matriz creada siempre es 26x26. Así que, en principio, está bien que pongas el valor fijo.

otronovato escribiste:Por otro lado, respecto al código que afronta el descifrado, he leído en la red sobre un operador ~~ "smart smatching", pero no he logrado hacerme una idea de cómo utilizarlo. La tarea que necesito es establecer el índice del array @vigenere que cuadra con el valor de clave que le paso en la condición. ¿Alguna idea?
Bueno, este operador lleva en modo "experimental" desde hace años. Debes leer la documentación de tu versión específica de Perl, para saber cómo funciona. Busca por "smartmatch", dentro de perlsyn. Pero, para lo que quieres hacer... también se puede hacer con hashes.

otronovato escribiste:Ya puestos, no he encontrado otra forma de acceder a las listas que componen @vigenere sino elemento a elemento de cada lista. ¿Cómo se accede a cada elemento del array, (cada lista), en bloque?
Pues como si fueran arrays. En perldata y perllol tienes ejemplos.

Ejemplo:

my @segunda_fila = @{ $vigenere[1] }; # copia de la segunda fila de @vigenere
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Error raro en script cifrado y descifrado Vigenère

Notapor otronovato » 2013-08-28 17:16 @761

:oops:

¡Vaya!... ¡Pues no veas la de rato que me he pegado sin darme cuenta de que no era el array cuya longitud necesitaba!

En cuanto a:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my @segunda_fila = @{ $vigenere[1] }; # copia de la segunda fila de @vigenere
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


:roll:

¡Ufffffff! ¡Según se entra en "Intermediate Perl" a la derecha...! El caso es que había probado y me daba error. Debo haberme confundido en la construcción y me he buscado una "solución" por otro lado. Me parece que debo tener más paciencia al depurar.

Me voy a pegar un rato con la documentación... Pero mi inglés es tan malo que hasta un programa Perl ofuscado podría llegar a parecerme más claro en ocasiones :lol:

Muchas gracias, explorer.
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Re: Error raro en script cifrado y descifrado Vigenère

Notapor explorer » 2013-08-28 18:06 @795

otronovato escribiste:Me voy a pegar un rato con la documentación... Pero mi inglés es tan malo que hasta un programa Perl ofuscado podría llegar a parecerme más claro en ocasiones :lol:
Hay por ahí unos locos que están traduciendo la documentación... :)

Algo llevan hecho...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Error raro en script cifrado y descifrado Vigenère

Notapor otronovato » 2013-08-28 18:10 @798

:o

¡Bendita locura!

Gracias de nuevo. :)

P. D.: Mi inglés es muy básico, mis conocimientos de Perl rudimentarios. Pero dado que voy a leer la documentación traducida, os tendré al corriente de cualquier incidencia, errata, etc.
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Re: Error raro en script cifrado y descifrado Vigenère

Notapor otronovato » 2013-08-28 18:42 @820

Más bugs :oops:

El código que extiende la clave a la longitud del mensaje debe ser éste:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #Extendemos la clave hasta el tamaño del mensaje
  2. my @clave_ext;
  3.  
  4. for(my $ind = 0;$ind <= $#mensaje;$ind++){
  5.  
  6.     ($ind <= $#clave) ? ($clave_ext[$ind]=$clave[$ind]):($clave_ext[$ind] = $clave[($ind % ($#clave+1))]);
  7. }
  8.  
  9.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


PS: No tiene importancia, pero que quede constancia de que, a la de cien, me doy cuenta de las cosas... :lol:
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Re: Error raro en script cifrado y descifrado Vigenère

Notapor explorer » 2013-08-29 06:46 @324

Bueno, es algo rebuscado, pero creo que está bien.

Mejor escrito, sería así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. # Extendemos la clave hasta el tamaño del mensaje
  2. my @clave_ext;
  3.  
  4. for my $i (0 .. $#mensaje) {
  5.     $clave_ext[$i] = $clave[$i % @clave];
  6. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Estas son dos de las soluciones más cortas que se me han ocurrido:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my @clave_ext = ( (@clave) x (1 + @mensaje/@clave) )[0 .. $#mensaje];
my @clave_ext = map { $clave[ $_ % @clave ] } 0 .. $#mensaje;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
La explicación del funcionamiento queda como ejercicio ;)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Error raro en script cifrado y descifrado Vigenère

Notapor otronovato » 2013-08-29 12:01 @542

:)

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my @clave_ext = ( (@clave) x (1 + @mensaje/@clave) )[0 .. $#mensaje];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El array @clave_ext, de dimensión igual a la de @mensaje, recibe la lista de caracteres contenida en @clave repetida ( 1 + longitud_de_@mensaje/longitud_de_@clave) veces. O sea:

supongamos que $long_clave = @clave = 3 y $long_mensaje = @mensaje = 17:

@clave_ext recibirá @clave x (1 + 17/3). Sabiendo que Perl transforma los flotantes en enteros truncando hacia abajo, @clave se repetiría 1 + 5 = 6 veces lo que son 18 elementos. ¡Pero como hemos fijado la longitud del array en 17 elementos mediante [0 .. $#mensaje], los sobrantes no entran en @clave_ext, sino que se van al cielo de /dev/null :shock:

En cuanto al map:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my @clave_ext = map { $clave[ $_ % @clave ] } 0 .. $#mensaje;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


A ver... $_ recibe los enteros de la lista (0 .. $#mensaje) y hace que en cada elemento de @clave_ext se almacene el elemento $clave[$_ % @clave].

Por ejemplo si $#mensaje = 14 y $#clave = 3, $clave_ext[0] = $clave[0 % 3] = $clave[0];
$clave_ext[1] = $clave[1 % 3]= $clave[1]... $clave_ext[3] = $clave[3 % 3]= $clave[0]...

:o

¡Ahora sé que jamás seré un buen programador...!

:lol:
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Re: Error raro en script cifrado y descifrado Vigenère

Notapor explorer » 2013-08-29 20:44 @905

otronovato escribiste:¡Ahora sé que jamás seré un buen programador...!
Yo también me lo digo... quizás por eso estoy sin trabajo :(

Otra cosa: esta mi versión del algoritmo Vigenère
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. #
  3. # Codificación en Vigenére
  4. #
  5. # Joaquín Ferrero, 20130829
  6. #
  7. # https://es.wikipedia.org/wiki/Cifrado_de_Vigen%C3%A8re
  8. #
  9.  
  10. use v5.14;
  11. use utf8::all;
  12.  
  13. @ARGV == 2 or die "Uso: $0 <clave> <mensaje>\n";
  14.  
  15. my($clave, $mensaje) = @ARGV;
  16.  
  17. my @alfabeto = ('A' .. 'N', 'Ñ', 'O' .. 'Z');
  18. my %alfa_num = map { $alfabeto[$_] => $_ } 0 .. $#alfabeto;
  19.  
  20. my $largo_clave   = length $clave;
  21. my $largo_mensaje = length $mensaje;
  22.  
  23. my $codificado;
  24.  
  25. for my $i (0 .. $largo_mensaje-1) {
  26.  
  27.     $codificado
  28.         .= $alfabeto[
  29.                 (
  30.                     $alfa_num{ substr $mensaje, $i, 1 }
  31.                     +                                                   # cambiar por '-', para decodificar
  32.                     $alfa_num{ substr $clave, $i % $largo_clave, 1 }
  33.                 )
  34.                 % @alfabeto
  35.            ]
  36.         ;
  37. }
  38.  
  39. say $codificado;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
El funcionamiento del programa está basado en la expresión matemática del algoritmo (ver la página de Wikipedia).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Error raro en script cifrado y descifrado Vigenère

Notapor otronovato » 2013-08-30 20:00 @875

Desde luego tu solución matemática es mucho más elegante y sencilla. Por mi parte quería desarrollar el proceso de cifrado y descifrado tal y como se hace "a mano". Aún me quedan un buen montón de métodos clásicos a "lápiz y papel" que me gustaría resolver y atacar de esta manera.

Si después de éso llego a ser capaz de comprender el cifrado "Pontifex" de "El Criptonomicón" sabré que he conseguido un cierto nivel de Perl. :lol:

Tu algoritmo me parece muy curioso:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.  
  2. for my $i (0 .. $largo_mensaje-1) {
  3.  
  4.     $codificado
  5.         .= $alfabeto[
  6.                 (
  7.                     $alfa_num{ substr $mensaje, $i, 1 }
  8.                     +                                                   # cambiar por '-', para decodificar
  9.                     $alfa_num{ substr $clave, $i % $largo_clave, 1 }
  10.                 )
  11.                 % @alfabeto
  12.            ]
  13.         ;
  14. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Hasta la fecha siempre había trabajado convirtiendo la cadena en array mediante split y operando sobre cada carácter, pero la solución de usar substr y trabajar directamente con cadenas no me había pasado por la cabeza. Desde luego esta forma de trabajar economiza variables.

Un saludo de un compañero de tu misma empresa :wink:
otronovato
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2013-08-26 06:12 @300

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 20 invitados