miércoles, 8 de abril de 2009

Búsqueda de Patrones en Cifrados de Sustitución

Cuando se realiza el criptoanálisis de un cifrado de sustitución monoalfabética, suele ser necesario encontrar palabras que encajen en ciertos patrones de letras. Por ejemplo, en un patroón como AACBBDA encajarían palabras como arrollar, guerrilleroencarrillar. Muchas veces, para encontrar estas palabras no es suficiente con nuestra imaginación y conocimiento de la lengua, por lo que suele ser útil recurrir al ordenador.
A continuación, pego un programa que permite realizar este tipo de búsquedas de forma muy sencilla.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void remove_nl(char *str)
{
   if(str[strlen(str)-1]=='\n')
      str[strlen(str)-1]=0;
}

int match_pattern(char *match, const char *pattern, size_t pattern_len)
{
   int i,j;

   for(i=0; i<pattern_len; i++)
   {
      for(j=i; j<pattern_len; j++)
      {
         if(pattern[i]==pattern[j])
            if(match[i]!=match[j])
               return 0;

         if(pattern[i]!=pattern[j])
            if(match[i]==match[j])
               return 0;
      }
   }

   return 1;
}

int main(int argc, char *argv[])
{
   char word[64];
   char *pattern = NULL;
   int pattern_len = 0;

   if(argc!=3)
   {
      printf("Usage: %s [word list] [crypto-pattern]\n\n", argv[0]);
      return 0;
   }

   pattern = argv[2];
   pattern_len = strlen(pattern);

   FILE *file = fopen(argv[1], "r");
   if(!file)
   {
      perror("fopen()");
      exit(0);
   }

   while(!feof(file))
   {
      fgets(word, sizeof(word), file);
      remove_nl(word);

      char *substr = word;

      while(strlen(substr)>=pattern_len)
      {
         if(strlen(substr)<pattern_len)
            break;

         char match[pattern_len];
         strncpy(match, substr, pattern_len);
         match[pattern_len]=0;

         if(match_pattern(match, pattern, pattern_len))
            printf("%s\n", word);

         substr++;
      }
   }


   fclose(file);

   return 0;
}




Para el patrón del ejemplo bastarí con compilar el programa con:

$ gcc pattern.c -o pattern

Y ejecutarlo con:

$  ./pattern ../dict/spanish AACBBDA
acurrullar
aporrillarse
arrollar
arrullar
aturrullar
barrillar
barrillera
barrillero
carrillera
cerrillar
churrillera
churrillero
churrullera
churrullero
corrillera
corrillero
desarrollar
descarrillar
emborrullarse
emparrillar
encarrillar
guerrillero
marrullera
marrulleria
marrullero
pantorrillera
zarzaparrillar

Espero que os sirva para vuestros cripoanalisis!

No hay comentarios: