% Breaking a reused one-time pad

% This is a function to read in  two files that
% have been encoded using the same sequence of
% random shifts (only letters are shifted, space
% are left alone).
% It them promts the user to guess a string in the 
% second text and tries this string in all 
% positions, and ranks positions acordding to the
% letter paircounting test.  The top five positions 
% are presented to the user, who can select one to 
% keep. Then the process is repeated.

function   break_reusedpad(filename1,filename2)
   % read in file to be encrypted/decrypted
   fileID1=fopen(filename1);
   input_text=fread(fileID1)';
   fclose(fileID1);
   cypher1=input_text;
   fileID2=fopen(filename2);
   input_text=fread(fileID2)';
   fclose(fileID2);
   cypher2=input_text;
   N=min(length(cypher1), length(cypher2));
   decrypt1=46*ones(1,N);
   decrypt2=46*ones(1,N);
   char(decrypt1)
   char(decrypt2)
   cypher1=cypher1-65;
   cypher2=cypher2-65;
   % subtract the cyphers  
   for k=1:N
        cypher(k)=mod(cypher1(k)-cypher2(k),27);
   end 
   cypher=[0,cypher];

   char(cypher(1:20)+65);
   % create matrix to use in count_pairs test
   matrix=pair_freq('ppall.txt');
   % throw away all entries  excepts letters and spaces
   % convert all letters to uppercase
   flag=0;
   while flag==0
       clear word;
       clear word2;
       clear word3;
       clear word4;
       clear word5;
       word=input('input word to test in quotes (enter 0 to exit): ');
       if word == 0
            return
       end
       counter=0;
       for k=1:length(word)
          letter=word(k);
          if letter ==32
              counter=counter+1;
              word2(counter)=91;
          elseif (65<=letter)&&(letter<=90)
              counter=counter+1;
              word2(counter)=letter;
          elseif (97<=letter)&&(letter<=122)
             counter=counter+1;
             word2(counter)=letter-32;
          end
      end
      char(word2)
      clear total;
      clear word3;
      clear saveword;
      L=length(word2)
      for k=1:length(cypher)-L
         for j=1:length(word2)
            word3(j)= mod((cypher(k+j))+(word2(j)-65),27);
         end
         if k<10
             char(word3+65)
         end 
         saveword(k,1:L)=word3;
         total(k)=count_pairs(matrix, word3+1);
      end
      figure
      hold on
      title('Plot of COUNT-PAIR score for different positions');
      plot(total)
      [m,pos]=sort(total,'descend');
      scatter(pos(1:5),total(pos(1:5)),'r','filled');
      pos(1:5)
      t=[1:5];
      for k=t
          best_pos=pos(k)
          word5(k,1)=48+k;
          word5(k,2)=32;
          word5(k,3)=32;
          for j=1:length(word2)
              word5(k,4:4+length(word2)-1)=65+saveword(best_pos,:);
          end
          word4(k,1:L)=65+saveword(best_pos,:);
      end
      char(word5)
      yesno=input('Which one to accept (none = 0)? ');
      if yesno>0  % update decrypt
          yesno
          bp=pos(yesno)
          char(word2)
          char(word4(1,:))
          length(word2)
          decrypt1(bp:bp+L-1)=word4(yesno,1:L);
          decrypt2(bp:bp+L-1)=word2 ;
          char(decrypt1)
          %t1
          char(decrypt2)
          %t2
      end
      % cheat t1 t2
     % char(word2)
     %    list=strfind(t2,word2)
     % for k=1:length(list)
     %     char(t1(list(k):list(k)+length(word)))
     %     char(t2(list(k):list(k)+length(word)))
     % end
   end % while
   return 
