El script es éste:
Using perl Syntax Highlighting
- #!/usr/bin/perl
- #Programa de cifrado Vigenère
- use strict;
- use warnings;
- use utf8::all;
- #Creamos la matriz 27 x 27 de Vigenère mediante un array de referencias a otros arrays
- my @alfa = ('A'..'N','Ñ','O'..'Z');
- my @num = (0..26);
- my %contacto;
- @contacto{@alfa}=@num;
- my @vigenere = (['A'..'N','Ñ','O'..'Z']);
- my $cont;
- my $cont2;
- my $fila;
- my $col;
- my @cifra;
- my @descifrado;
- for($cont=1;$cont<=26;$cont++){
- for($cont2=0;$cont2<=26;$cont2++){
- $vigenere[$cont]->[$cont2] = $vigenere[$cont-1]->[$cont2];
- }
- my $prim_car = shift $vigenere[$cont];
- push $vigenere[$cont], $prim_car;
- }
- #Comprobamos que la matriz está correctamente poblada
- for($fila=0;$fila<=$#vigenere;$fila++){
- print "\n";
- for($col=0;$col<=26;$col++){
- print $vigenere[$fila]->[$col];
- }
- }
- print "\n";
- #Recogemos la clave y el mensaje de la línea de comandos
- #Suponemos que se trata de una cadena de mayúsculas sin espacios en blanco
- my @clave = split //,$ARGV[0];
- my @mensaje = split //, $ARGV[1];
- #Extendemos la clave hasta el tamaño del mensaje
- my @clave_ext;
- for(my $ind = 0;$ind <= $#mensaje;$ind++){
- ($ind <= $#clave) ? ($clave_ext[$ind]=$clave[$ind]):($clave_ext[$ind] = $clave[($ind % $#clave)-1]);
- }
- print "La clave es ", join '',@clave, "\n";
- print "La clave extendida es ", join '', @clave_ext, "\n";
- print "El mensaje es ", join '', @mensaje, "\n";
- #Algoritmo de vigenere propiamente dicho
- for(my $cnt = 0;$cnt<= $#mensaje;$cnt++){
- my $car = $mensaje[$cnt];
- my $key = $clave_ext[$cnt];
- #Busco la fila de @vigenere que concuerde con $key gracias al hash %contacto.
- my $fil = $contacto{$key};
- #Extraemos la columna de @vigenere que concuerda con el carácter de mensaje.
- my $colum = $contacto{$car};
- print $car, "\t", $key, "\t", $fil, "\t", $colum,"\n";
- #Extraemos el valor correspondiente y lo introducimos en @cifra.
- push @cifra, $vigenere[$fil]->[$colum];
- }
- print @cifra, "\n";
- #Desciframos el mensaje
- for(my $cnt2 = 0;$cnt2<=$#cifra;$cnt2++){
- my $columna;
- my $car = $cifra[$cnt2];
- my $key = $clave_ext[$cnt2];
- my $fil = $contacto{$key};
- for(my $cnt3=0;$cnt3<=26;$cnt3++){
- if($car eq $vigenere[$fil]->[$cnt3]){
- $columna = $cnt3;
- }
- }
- push @descifrado, $vigenere[0]->[$columna];
- }
- print "El mensaje era \t", @descifrado, "\n";
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4
El resultado es el siguiente:
- xxxxx@xxxxx:~/Escritorio/scripts_criptografía$ ./vigenere.pl ABCDEF LAHERMOSAYGRACIOSANIÑAMARCHOSEALAVARLAROPA
- ABCDEFGHIJKLMNÑOPQRSTUVWXYZ
- BCDEFGHIJKLMNÑOPQRSTUVWXYZA
- CDEFGHIJKLMNÑOPQRSTUVWXYZAB
- DEFGHIJKLMNÑOPQRSTUVWXYZABC
- EFGHIJKLMNÑOPQRSTUVWXYZABCD
- FGHIJKLMNÑOPQRSTUVWXYZABCDE
- GHIJKLMNÑOPQRSTUVWXYZABCDEF
- HIJKLMNÑOPQRSTUVWXYZABCDEFG
- IJKLMNÑOPQRSTUVWXYZABCDEFGH
- JKLMNÑOPQRSTUVWXYZABCDEFGHI
- KLMNÑOPQRSTUVWXYZABCDEFGHIJ
- LMNÑOPQRSTUVWXYZABCDEFGHIJK
- MNÑOPQRSTUVWXYZABCDEFGHIJKL
- NÑOPQRSTUVWXYZABCDEFGHIJKLM
- ÑOPQRSTUVWXYZABCDEFGHIJKLMN
- OPQRSTUVWXYZABCDEFGHIJKLMNÑ
- PQRSTUVWXYZABCDEFGHIJKLMNÑO
- QRSTUVWXYZABCDEFGHIJKLMNÑOP
- RSTUVWXYZABCDEFGHIJKLMNÑOPQ
- STUVWXYZABCDEFGHIJKLMNÑOPQR
- TUVWXYZABCDEFGHIJKLMNÑOPQRS
- UVWXYZABCDEFGHIJKLMNÑOPQRST
- VWXYZABCDEFGHIJKLMNÑOPQRSTU
- WXYZABCDEFGHIJKLMNÑOPQRSTUV
- XYZABCDEFGHIJKLMNÑOPQRSTUVW
- YZABCDEFGHIJKLMNÑOPQRSTUVWX
- ZABCDEFGHIJKLMNÑOPQRSTUVWXY
- La clave es ABCDEF
- La clave extendida es ABCDEFABCDFABCDFABCDFABCDFABCDFABCDFABCDFA
- El mensaje es LAHERMOSAYGRACIOSANIÑAMARCHOSEALAVARLAROPA
- L A 0 11
- A B 1 0
- H C 2 7
- E D 3 4
- R E 4 18
- M F 5 12
- O A 0 15
- S B 1 19
- A C 2 0
- Y D 3 25
- G F 5 6
- R A 0 18
- A B 1 0
- C C 2 2
- I D 3 8
- O F 5 15
- S A 0 19
- A B 1 0
- N C 2 13
- I D 3 8
- Ñ F 5 14
- A A 0 0
- M B 1 12
- A C 2 0
- R D 3 18
- C F 5 2
- H A 0 7
- O B 1 15
- S C 2 19
- E D 3 4
- A F 5 0
- L A 0 11
- A B 1 0
- V C 2 22
- A D 3 0
- R F 5 18
- L A 0 11
- A B 1 0
- R C 2 18
- O D 3 15
- P F 5 16
- A A 0 0
- LBJHVQOTCBLRBELTSBOLSANCUHHPUHFLBXDWLBTRUA
- 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":
Using perl Syntax Highlighting
- for(my $cnt3=0;$cnt3<=26;$cnt3++){
- if($car eq $vigenere[$fil]->[$cnt3]){
- $columna = $cnt3;
- }
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:
- 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