Ignore:
Timestamp:
Jun 4, 2009, 2:54:00 PM (13 years ago)
Author:
Danail Vazov
Message:

Added an integer Array output for the keyword. When connected to the Vigenere plugins input of the same type, the Vigenere ciphers keyword is set to whatever was calculated in the VigenereAnalyser plugin.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/CrypPlugins/VigenereAnalyser/VigenereAnalyser.cs

    r324 r340  
    2121    public class VigenereAnalyser:IStatistic
    2222    {
    23         public bool waitForInput = false;
     23       
     24        private char[] validchars = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; //Sets alphabet of valid characters
     25        private int[] keywordOutput;
    2426        private string frequencyOutput="";
    2527        private string stringOutput = "";
     
    2729        private double friedmanInput;
    2830        private int [] kasiskiInput;
    29         private int frequencyInput;
     31        private int caesarKey;
     32        private string[] vigToCaes;
     33        private int v=0;
     34        private int probableKeylength = 0;
     35        int[] keys;
     36        //private bool inputChange = false;
     37       
     38       
    3039
    3140        #region Private methods
    32         private void WaitForInput()
    33         {
    34             long m = 0;
    35 
    36             while (waitForInput != true)
    37             {
    38 
    39                 m++;
    40             }
    41         }
     41       
    4242        private void ShowStatusBarMessage(string message, NotificationLevel logLevel)
    4343        {
     
    7575            set { stringInput = value; OnPropertyChanged("StringInput"); }
    7676        }
    77         [PropertyInfo(Direction.Input, "Integer Array.", "The Array cointains keylengths as proposed by the Kasiski Test.", "", true, true, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
     77        [PropertyInfo(Direction.Input, "Integer Array.", "The Array cointains keylengths as proposed by the Kasiski Test.", "", false, true, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
    7878        public int[] KasiskiInput
    7979        {
     
    8989            }
    9090        }
    91         [PropertyInfo(Direction.Input, "Shift value (integer)", "Input from the CaesarAnalysisHelper.", "", true, true, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
    92         public int FrequencyInput
    93         {
    94             get { return frequencyInput; }
    95             set
    96             {
    97                 if (value != frequencyInput)
    98                 {
    99                     frequencyInput = value;
    100                     OnPropertyChanged("FrequencyInput");
    101                     waitForInput = true;
    102                    
     91        [PropertyInfo(Direction.Output, "Integer Array.", "Keyword represented as an integer Array.", "", false, true, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
     92        public int[] KeywordOutput
     93        {
     94            get { return keywordOutput; }
     95            set
     96            {
     97                if (value != keywordOutput)
     98                {
     99                    keywordOutput = value;
     100                    OnPropertyChanged("KeywordOutput");
     101
     102                }
     103            }
     104        }
     105        [PropertyInfo(Direction.Input, "String", "Please only connect to the text output of the Frequency Test.", "", true, true, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
     106        public int CaesarKey
     107        {
     108            get { return caesarKey; }
     109            set
     110            {
     111                if (value != caesarKey)
     112                {
     113                    caesarKey = value;
     114                    OnPropertyChanged("CaesarKey");
     115                    //inputChange = true;
     116                    v++;
    103117                }
    104118            }
     
    148162            //throw new NotImplementedException();
    149163        }
    150 
     164        public void PreExecution()
     165        {
     166           
     167            caesarKey = 0;
     168            frequencyOutput = null;
     169            vigToCaes = null;
     170            probableKeylength = 0;
     171            //inputChange = false;
     172            keys = null;
     173           
     174
     175        }
    151176        public void Execute()
    152177        {
    153             if (kasiskiInput !=null)
    154             {
    155                 double friedmanKey = friedmanInput;
    156                 int[] kasiskiFactors = kasiskiInput;
    157                 string workString = stringInput;
    158                 string workstring2 = "";
    159                 int probableKeylength=0;
    160                 //Convert the cipher text into a format suitable for analysing i.e. remove all non-plaintext characters.
    161                 char[] validchars = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; //Sets alphabet of valid characters
    162                 string strValidChars = new string(validchars);
    163                 StringBuilder workstring1 = new StringBuilder();
    164                 char[] workStringArray = workString.ToCharArray();
    165                 foreach (char c in workStringArray)
    166                 {
    167                     if (strValidChars.IndexOf(c) >= 0) //If a char from the workString is valid, it is  appended to a newly built workstring1
    168                     {
    169                         workstring1.Append(c);
    170                     }
    171                 }
    172 
    173                 workstring2 = workstring1.ToString(); // Now copy workstring1 to workstring2. Needed because workstring1 can not be altered once its built
    174                 workstring2 = workstring2.ToLower();
    175                 string cipherText = workstring2;
    176                 //Start analysing the keylenghts proposed by the Friedman and Kasiski tests, and find the most propbable keylength.
    177                 int [] primes = new int [] {  3   ,   5  ,    7  ,   11   ,  13   ,  17  ,   19 ,    23  ,   29 ,
     178           if (kasiskiInput != null)
     179            {
     180                if (vigToCaes==null)
     181                {
     182                    double friedmanKey = friedmanInput;
     183                    int[] kasiskiFactors = kasiskiInput;
     184                    string workString = stringInput;
     185                    string workstring2 = "";
     186                    //int probableKeylength=0;
     187                    //Convert the cipher text into a format suitable for analysing i.e. remove all non-plaintext characters.
     188                   
     189                    string strValidChars = new string(validchars);
     190                    StringBuilder workstring1 = new StringBuilder();
     191                    char[] workStringArray = workString.ToCharArray();
     192                    foreach (char c in workStringArray)
     193                    {
     194                        if (strValidChars.IndexOf(c) >= 0) //If a char from the workString is valid, it is  appended to a newly built workstring1
     195                        {
     196                            workstring1.Append(c);
     197                        }
     198                    }
     199
     200                    workstring2 = workstring1.ToString(); // Now copy workstring1 to workstring2. Needed because workstring1 can not be altered once its built
     201                    workstring2 = workstring2.ToLower();
     202                    string cipherText = workstring2;
     203                    //Start analysing the keylenghts proposed by the Friedman and Kasiski tests, and find the most propbable keylength.
     204                    int[] primes = new int[] { 5  ,    7  ,   11   ,  13   ,  17  ,   19 ,    23  ,   29 ,
    178205                31   ,  37  ,   41 ,    43  ,   47  ,   53}; //Basic Array of prime numbers...replace with a primes generator or some sieve algorithm???
    179                 int biggestSoFar = 0;
    180                 int biggestSoFarIndex = 0;
    181                 int z = 0;
    182                 //Now we initialize an empty jagged array in which plausable keylengths with their respective probabilities will be stored
    183                 int[][] proposedKeylengths =
     206                    int biggestSoFar = 0;
     207                    int biggestSoFarIndex = 0;
     208                    int z = 0;
     209                    //Now we initialize an empty jagged array in which plausable keylengths with their respective probabilities will be stored
     210                    int[][] proposedKeylengths =
    184211                {
    185212                 new int[] {0,0,0,0,0,0,0,0,0,0,0},
     
    187214   
    188215                };
    189                 //Fill up the array
    190                 for (int j = kasiskiFactors.Length - 1; j >= 0; j--)
    191                 {
     216                    //Fill up the array
     217                    for (int j = kasiskiFactors.Length - 1; j >= 0; j--)
     218                    {
    192219                        if (kasiskiFactors[j] > biggestSoFar)
    193220                        {
    194221                            biggestSoFar = kasiskiFactors[j];
    195222                            biggestSoFarIndex = j;
    196                             proposedKeylengths[0][z]= j;
     223                            proposedKeylengths[0][z] = j;
    197224                            proposedKeylengths[1][z] = kasiskiFactors[j];
    198225                            z++;
    199                                
    200                          }
    201                 }
    202                 //The resulting array contains some plausible keylengths and some not so plausible keylengths.
    203                 //The variable "biggestSoFarIndex" contains the most common factor, hence most plausible keylength. Problem - biggestSoFarIndex is 2...
    204 
    205                 //After the most common factor is found check if this factor is a prime number. If yes - job done, this is indeed the key length.
    206                 foreach (int s in primes)
    207                 {
    208                     if (s == biggestSoFarIndex)
    209                     {
    210                         probableKeylength = biggestSoFarIndex; break;
    211                     }
    212                 }
    213                 //In case the most common factor is not prime...well tough luck. We'll have to make some assumptions...
    214                 //First of all let's sort out unprobable keylengths.
    215                 double check1 = 0.55 * biggestSoFar;
    216                 int check = Convert.ToInt32(check1);
    217                 for (int r = 0; r <= proposedKeylengths[0].Length - 1;r++ )
    218                 {
     226
     227                        }
     228                    }
     229                    //The resulting array contains some plausible keylengths and some not so plausible keylengths.
     230                    //The variable "biggestSoFarIndex" contains the most common factor, hence most plausible keylength. Problem - biggestSoFarIndex is 2...
     231
     232                    //After the most common factor is found check if this factor is a prime number. If yes - job done, this is indeed the key length.
     233                    foreach (int s in primes)
     234                    {
     235                        if (s == biggestSoFarIndex)
     236                        {
     237                            probableKeylength = biggestSoFarIndex;
     238                            goto Massages;
     239                        }
     240                    }
     241                    //In case the most common factor is not prime...well tough luck. We'll have to make some assumptions...
     242                    //First of all let's sort out unprobable keylengths.
     243                    double check1 = 0.55 * biggestSoFar;
     244                    int check = Convert.ToInt32(check1);
     245                    for (int r = 0; r <= proposedKeylengths[0].Length - 1; r++)
     246                    {
    219247                        if (proposedKeylengths[1][r] < check)
    220248                        {
     
    223251                        }
    224252
    225                 }
    226                 //The unprobalbe keylengths are now replaced with zeroes.
    227                 //Get rid of the zeroes...
    228                 ArrayList factors = new ArrayList();
    229                 ArrayList count = new ArrayList();
    230                 for (int d = 0; d <= proposedKeylengths[0].Length - 1; d++)
    231                 {
    232                     if (proposedKeylengths[0][d] != 0)
    233                     {
    234                         factors.Add(proposedKeylengths[0][d]);
    235                         count.Add(proposedKeylengths[1][d]);
    236                     }
    237                 }
    238                 //The dynamic arrays "factors" and "count" now contain only the most prorbale keylengths and their respective probability.
    239                 //For ease of access convert the dynamic arrays in to normal ones
    240                 int [] factors1=(int[])factors.ToArray(typeof(int));
    241                 int [] count1 = (int[])count.ToArray(typeof(int));
    242                 int a = factors1.Length;
    243                 //Now check the difference in probability between the most common and most uncommon factors
    244                 double smallestCount = count1[0]; //c# does not implicitly convert between int and double, hence two new variables are needed
    245                 double biggestCount = count1[a - 1];
    246                 double controlValue = smallestCount/biggestCount;
    247                 //Now can make some assumptions...
    248                 if (a > 3)
    249                 {
    250                     if (factors1[0] % factors1[a-1] == 0 && factors1[0] % factors1[a - 2] == 0 && factors1[0] % factors1[a - 3] == 0&&controlValue>0.65)
     253                    }
     254                    //The unprobalbe keylengths are now replaced with zeroes.
     255                    //Get rid of the zeroes...
     256                    ArrayList factors = new ArrayList();
     257                    ArrayList count = new ArrayList();
     258                    for (int d = 0; d <= proposedKeylengths[0].Length - 1; d++)
     259                    {
     260                        if (proposedKeylengths[0][d] != 0)
     261                        {
     262                            factors.Add(proposedKeylengths[0][d]);
     263                            count.Add(proposedKeylengths[1][d]);
     264                        }
     265                    }
     266                    //The dynamic arrays "factors" and "count" now contain only the most prorbale keylengths and their respective probability.
     267                    //For ease of access convert the dynamic arrays in to normal ones
     268                    int[] factors1 = (int[])factors.ToArray(typeof(int));
     269                    int[] count1 = (int[])count.ToArray(typeof(int));
     270                    int a = factors1.Length;
     271                    //Now check the difference in probability between the most common and most uncommon factors
     272                    double smallestCount = count1[0]; //c# does not implicitly convert between int and double, hence two new variables are needed
     273                    double biggestCount = count1[a - 1];
     274                    double controlValue = smallestCount / biggestCount;
     275                    //Now can make some assumptions...
     276                    if (a > 3)
     277                    {
     278                        if (factors1[0] % factors1[a - 1] == 0 && factors1[0] % factors1[a - 2] == 0 && factors1[0] % factors1[a - 3] == 0 && controlValue > 0.65)
     279                        {
     280                            probableKeylength = factors1[0];
     281                        }
     282                    }
     283                    if (a == 3)
     284                    {
     285                        if (factors1[0] % factors1[a - 1] == 0 && factors1[0] % factors1[a - 2] == 0 && controlValue > 0.75)
     286                        {
     287                            probableKeylength = factors1[0];
     288                        }
     289                        if (factors1[0] % factors1[a - 2] == 0 && factors1[0] % factors1[a - 1] != 0 && controlValue > 0.6)
     290                        {
     291                            probableKeylength = factors1[0];
     292                        }
     293
     294                    }
     295                    if (a == 2)
     296                    {
     297                        if (factors1[0] % factors1[a - 1] == 0 && controlValue > 0.75)
     298                        {
     299                            probableKeylength = factors1[0];
     300                        }
     301
     302                    }
     303                    if (a == 1)
    251304                    {
    252305                        probableKeylength = factors1[0];
    253306                    }
    254                 }
    255                 if (a == 3)
    256                 {
    257                     if (factors1[0] % factors1[a - 1] == 0 && factors1[0] % factors1[a - 2] == 0 && controlValue > 0.75)
    258                     {
    259                         probableKeylength = factors1[0];
    260                     }
    261                     if (factors1[0] % factors1[a - 2] == 0 && factors1[0] % factors1[a - 1] != 0 && controlValue > 0.6)
    262                     {
    263                         probableKeylength = factors1[0];
    264                     }
    265  
    266                 }
    267                 if (a == 2)
    268                 {
    269                     if (factors1[0] % factors1[a - 1] == 0 && controlValue > 0.75)
    270                     {
    271                         probableKeylength = factors1[0];
    272                     }
     307                    //Now that we've made some rudimentary decission making, let's check if it has payed off...
     308                Massages:
     309                    if (Math.Abs(probableKeylength - friedmanKey) < 1)
     310                    {
     311                        ShowStatusBarMessage("Analysed proposed keylengths. The derived keylength is the correct value." + "" + "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
     312                    }
     313                    if (Math.Abs(probableKeylength - friedmanKey) > 1 && Math.Abs(probableKeylength - friedmanKey) < 2)
     314                    {
     315                        ShowStatusBarMessage("Analysed proposed keylengths. The derived keylength is probably the correct value" + "" + "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
     316                    }
     317                    if (Math.Abs(probableKeylength - friedmanKey) > 2 && Math.Abs(probableKeylength - friedmanKey) < 3)
     318                    {
     319                        ShowStatusBarMessage("Analysed proposed keylengths. The derived keylength may not be the correct value." + "" + "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
     320                    }
     321                    if (Math.Abs(probableKeylength - friedmanKey) > 3)
     322                    {
     323                        ShowStatusBarMessage("Analysed proposed keylengths. Friedman or Kasiski test provided a value that was wrong. A manual analysis may be needed to confirm the derived keylength." + "" + "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
     324                    }
     325                    //Now we have a good idea of the keylength used to encrypt the ciphertext recived on the stringInput.
     326                    //Let's start with the analysis of the Vigenere cipher proper.
     327                    //First we need to divide the cipher text into columns. The number of columns must be equal to the probableKeylength.
     328                    //Create an array of strings. Just a container for the columns.
     329                    char[] cipherTextChars = cipherText.ToCharArray();
     330                    int l = 0;
     331                    //Now we fill up the vigenereToCeasar array with strings.
     332                    string[] vigenereToCaesar = new string[probableKeylength];
     333                    for (int b = 0; b <= probableKeylength - 1; b++)
     334                    {
     335                        StringBuilder tempstring = new StringBuilder();
     336                        for (l = b; l <= cipherTextChars.Length - 1; l = l + probableKeylength)
     337                        {
     338                            tempstring.Append(cipherTextChars[l]);
     339                        }
     340                        vigenereToCaesar[b] = tempstring.ToString();
     341                        tempstring = null;
     342                    }
     343                    //After the outer loop is executed probableKeylength-times every element of vigenereToCaesar contains a string.
     344                    //Each of those strings should be alligned to the same keyletter of the Vigenere key which was used to encrypt the analysed text.
     345                    //Hence each string is encrypted using the Caeser cipher, and a Frequency Test for each string should give us a good idea of what the shift key is for the respective string.
     346                    //Furthermore the vigenerToCaesar is allready sorted in such a way that the index of each element coresponds to the position of its respective shift key in the whole key.
     347                    vigToCaes = vigenereToCaesar;
     348                    keys = new int[probableKeylength + 1];
     349                    factors1 = null;
    273350                   
    274351                }
    275                 //Now that we've made some rudimentary decission making, let's check if it has payed off...
    276                 if (Math.Abs(probableKeylength - friedmanKey) < 1)
    277                 {
    278                     ShowStatusBarMessage("Analysed proposed keylengths. The derived keylength is the correct value." +""+ "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
    279                 }
    280                 if (Math.Abs(probableKeylength - friedmanKey) > 1 && Math.Abs(probableKeylength - friedmanKey)<2)
    281                 {
    282                     ShowStatusBarMessage("Analysed proposed keylengths. The derived keylength is probably the correct value" + "" + "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
    283                 }
    284                 if (Math.Abs(probableKeylength - friedmanKey) > 2 && Math.Abs(probableKeylength - friedmanKey) < 3)
    285                 {
    286                     ShowStatusBarMessage("Analysed proposed keylengths. The derived keylength may not be the correct value." + "" + "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
    287                 }
    288                 if (Math.Abs(probableKeylength - friedmanKey) > 3)
    289                 {
    290                     ShowStatusBarMessage("Analysed proposed keylengths. Friedman or Kasiski test provided a value that was wrong. A manual analysis may be needed to confirm the derived keylength." + "" + "Derived keylength is:" + probableKeylength.ToString(), NotificationLevel.Info);
    291                 }
    292                 //Now we have a good idea of the keylength used to encrypt the ciphertext recived on the stringInput.
    293                 //Let's start with the analysis of the Vigenere cipher proper.
    294                 //First we need to divide the cipher text into columns. The number of columns must be equal to the probableKeylength.
    295                 //Create an array of strings. Just a container for the columns.
    296                 string [] vigenereToCeasar=new string [probableKeylength];
    297                 char[] cipherTextChars = cipherText.ToCharArray();
    298                 int l=0;
    299                 //Now we fill up the vigenereToCeasar array with strings.
    300                 for (int b = 0; b <= probableKeylength - 1; b++)
    301                 {
    302                     StringBuilder tempstring = new StringBuilder();
    303                     for (l=b; l <= cipherTextChars.Length - 1; l=l+probableKeylength)
    304                     {
    305                         tempstring.Append(cipherTextChars[l]);
    306                     }
    307                     vigenereToCeasar[b] = tempstring.ToString();
    308                     tempstring = null;
    309                 }
    310                 //After the outer loop is executed probableKeylength-times every element of vigenereToCaesar contains a string.
    311                 //Each of those strings should be alligned to the same keyletter of the Vigenere key which was used to encrypt the analysed text.
    312                 //Hence each string is encrypted using the Caeser cipher, and a Frequency Test for each string should give us a good idea of what the shift key is for the respective string.
    313                 //Furthermore the vigenerToCaesar is allready sorted in such a way that the index of each element coresponds to the position of its respective shift key in the whole key.
    314                 int []keyFrequency=new int [probableKeylength];
    315                 for (int v = 0; v <= probableKeylength-1; v++)
    316                 {
    317                     frequencyOutput = vigenereToCeasar[v];
    318                     OnPropertyChanged("FrequencyOutput");
    319                     WaitForInput();
    320                     keyFrequency[v] = frequencyInput;
    321                     waitForInput = false;
    322                 }
    323                 stringOutput = probableKeylength.ToString();
    324                 OnPropertyChanged("StringOutput");
     352                if (vigToCaes != null)
     353                {
     354
     355
     356                    if (v <= probableKeylength - 1)
     357                    {
     358                        frequencyOutput = vigToCaes[v];
     359                        OnPropertyChanged("FrequencyOutput");
     360                    }
     361                    keys[v] = caesarKey;
     362
     363
     364
     365                }
     366               
     367              //After the loop on the workspace was executed probableKeylength-times the array keys contains the actual key in form of shift values.
     368               int []keyword=new int [keys.Length-1];
     369               int n = 0;
     370               if (v==probableKeylength)
     371               {
     372                   
     373                   for (int t = 1; t <= keys.Length - 1; t++)
     374                   {
     375                       keyword[n] = keys[t];
     376                       n++;
     377                   }
     378                   
     379               }
     380               if (keys.Length-1==n)
     381               {
     382                   keywordOutput = keyword;
     383                   OnPropertyChanged("KeywordOutput");
     384               }
     385               
    325386            }
    326387        }
     
    344405        public void PostExecution()
    345406        {
    346             //throw new NotImplementedException();
    347         }
    348 
    349         public void PreExecution()
    350         {
    351             //throw new NotImplementedException();
    352         }
     407            kasiskiInput = null;
     408            probableKeylength = 0;
     409            //inputChange = false;
     410            v = 0;
     411        }
     412
     413       
    353414
    354415        public System.Windows.Controls.UserControl Presentation
Note: See TracChangeset for help on using the changeset viewer.