source: trunk/CrypPlugins/VigenereAutokeyAnalyser/VigenereAutokeyAnalyser.cs @ 1597

Last change on this file since 1597 was 1597, checked in by nolte, 11 years ago

Added the VigenereAutokey-Analyser to the solution/CrypPlugInBase.
It can be found under the cryptanalyse-statistical tools...
it's already working...Missing Sample,Description and a new icon will follow soon.
I will also rewrite the code/comments soon so it will be more comfortable to read (on Thursday I suppose).

File size: 15.8 KB
Line 
1/* HOWTO: Change year, author name and organization.
2   Copyright 2010 Your Name, University of Duckburg
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16using System;
17using System.Collections.Generic;
18using System.Linq;
19using System.Text;
20using Cryptool.PluginBase;
21using System.ComponentModel;
22using Cryptool.PluginBase.IO;
23using Cryptool.PluginBase.Miscellaneous;
24using System.Windows.Controls;
25using Cryptool.PluginBase.Analysis;
26
27namespace Cryptool.Plugins.VigenereAutokeyAnalyser
28{
29    [Author("Dennis Nolte", "nolte@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
30    [PluginInfo(false, "VigenereAutokeyAnalyser", "Ciphertext-only attack on VigenereAutoKey encryption", null, "VigenereAutokeyAnalyser/icon.png")]
31
32    public class VigenereAutokeyAnalyser : IStatistic//IIOMisc
33    {
34        #region Private Variables
35
36        private readonly VigenereAutokeyAnalyserSettings settings = new VigenereAutokeyAnalyserSettings();
37        private String ciphertext = "";                             //The cipher to be analysed
38        private String alphabet;                                    //The alphabet to be used
39        private String key;                                         //One probable key
40        private double IC;                                          //One probable index of coincidence
41        private String completeplain;                               //One probable mixed up plaintext
42
43        private String textkorpus;                                  //Alternative to the predetermindet Frequencys in Languages
44
45        private int maxkeylength;                                   //The maximum keylength we search for
46        private int keylength;                                      //One probable keylength
47        private int language;                                       //Frequencys we work with
48        private double cSofS;                                       //One probable Ciphercolumn Sum of Squares
49        private int maxfactor;                                      //One probable multiple of the keylength
50       
51        //Frequency Section
52        private double[] OF = new double[255];                      //Observed Frequency for a ciphercolumn or completeplain
53        private double[] EF;                                        //Expected Frequency due to the expected language
54
55        //Reminder Section
56        private String finalkey;                                    //The solution
57        private double finalIC = 0.0;                               //The IC for the solution
58        private double sumofsquares;                                //The Sum of Squares for the best solution
59
60        #endregion
61
62        #region Data Properties
63
64
65        [PropertyInfo(Direction.InputData, "Cipher Input", "Enter your cipher here", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
66        public String InputCipher
67        {
68            get
69            {
70                return ciphertext;
71            }
72            set
73            {
74                this.ciphertext = value;
75                OnPropertyChanged("InputCipher");
76            }
77        }
78
79        [PropertyInfo(Direction.InputData, "Textkorpus Input", "Enter your sample text here or choose a language from the task-pane", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
80        public String InputKorpus
81        {
82            get
83            {
84                return textkorpus;
85            }
86            set
87            {
88                this.textkorpus = value;
89                OnPropertyChanged("InputKorpus");
90            }
91        }
92
93
94        [PropertyInfo(Direction.OutputData, "Key Output", "The most probable autokey for the analysed ciphertext", "", DisplayLevel.Beginner)]
95        public String OutputKey
96        {
97            get
98            {
99                return finalkey;
100            }
101            set
102            {
103                this.finalkey = value;
104                OnPropertyChanged("OutputKey");
105            }
106        }
107
108        #endregion
109
110        #region IPlugin Members
111
112        public ISettings Settings
113        {
114            get { return settings; }
115        }
116
117        /// <summary>
118        /// HOWTO: You can provide a custom (tabbed) presentation to visualize your algorithm.
119        /// Return null if you don't provide one.
120        /// </summary>
121        public UserControl Presentation
122        {
123            get { return null; }
124        }
125
126        /// <summary>
127        /// HOWTO: You can provide custom (quickwatch) presentation to visualize your algorithm.
128        /// Return null if you don't provide one.
129        /// </summary>
130        public UserControl QuickWatchPresentation
131        {
132            get { return null; }
133        }
134
135        public void PreExecution()
136        {
137        }
138
139        /// <summary>
140        /// HOWTO: Enter the algorithm you'd like to implement in this method.
141        /// </summary>
142        public void Execute()
143        {
144            ProgressChanged(0, 1);
145
146//Preparations for the Analyse-------------------------------------------------------------------------------------
147
148            alphabet = settings.AlphabetSymbols;
149
150            ciphertext = InputCipher;
151
152            ciphertext = prepareForAnalyse(ciphertext);
153
154            maxkeylength = (ciphertext.Length / 40) + 1;
155           
156            language = settings.Language;
157
158            if (textkorpus != null)
159            {
160                textkorpus = prepareForAnalyse(textkorpus);
161                EF = observedFrequency(textkorpus);
162            }
163            else
164            {
165                EF = expectedFrequency(language);
166            }
167
168//-----------------------------------------------------------------------------------------------------------------
169//Analyse----------------------------------------------------------------------------------------------------------
170//-----------------------------------------------------------------------------------------------------------------
171
172            for (int d = 1; d <= maxkeylength; d++)
173            {
174                completeplain = "";
175                key = "";
176                keylength = d;
177
178                maxfactor = ciphertext.Length / keylength;
179
180                for (int column = 0; column < keylength; column++)
181                {
182                    String ciphercolumn = "";
183                    char probablekeychar = 'A';
184                    sumofsquares = 99999999999.99999999999;
185
186                    for (int i = 0; i <= maxfactor; i++)
187                    {
188                        if (column + i * keylength < ciphertext.Length)
189                        {
190                            ciphercolumn = ciphercolumn + ciphertext[column + i * keylength];
191                        }
192                    }
193
194                    ciphercolumn = ciphercolumn.ToUpper();
195
196                    for (int shift = 0; shift < alphabet.Length; shift++)
197                    {
198                        cSofS = getSumOfSquares(ciphercolumn, shift);
199
200
201                        if (cSofS < sumofsquares)
202                        {
203                            sumofsquares = cSofS;
204                            probablekeychar = alphabet[shift];
205                        }
206
207
208                    }
209
210                    completeplain = getShift(ciphercolumn, getPos(probablekeychar)); //merkt sich die entciphertecolumn
211                    key = key + probablekeychar;
212
213
214
215                }
216                         
217
218                IC = getIC(completeplain);
219
220                if (IC > finalIC)
221                {
222                    finalIC = IC;
223                    finalkey = key;
224                }
225
226                ProgressChanged((((double)d) / maxkeylength), 1);
227           
228            }//This keylength checked...next one
229
230
231
232            OutputKey = finalkey;
233            OnPropertyChanged("OutputKey");
234
235//-----------------------------------------------------------------------------------------------------------------
236
237            ProgressChanged(1, 1);
238        }
239
240        public void PostExecution()
241        {
242        }
243
244        public void Pause()
245        {
246        }
247
248        public void Stop()
249        {
250        }
251
252        public void Initialize()
253        {
254        }
255
256        public void Dispose()
257        {
258        }
259
260        #endregion
261
262        #region Private Methods
263
264//GET IC---------------------------------------------------------------------------------------------------------------------------------
265
266        private double getIC(String completeplain)
267        {
268            OF = observedFrequency(completeplain);
269            IC = 0;
270
271            for (int x = 0; x < alphabet.Length; x++)
272            {
273                IC = IC + (OF[alphabet[x]] * OF[alphabet[x]]) / (1.0 / alphabet.Length);
274            }
275
276
277            return IC;
278        }
279
280
281//---------------------------------------------------------------------------------------------------------------------------------------
282//PREPARE PART---------------------------------------------------------------------------------------------------------------------------
283
284        private String prepareForAnalyse(String c)
285        {
286            String prepared = "";
287
288            c = c.ToUpper();
289
290            for (int x = 0; x < c.Length; x++)
291            {
292                if (getPos(c[x]) != -1)
293                {
294                    prepared = prepared + c[x];
295                }
296            }
297            return prepared;
298        }
299
300
301
302//---------------------------------------------------------------------------------------------------------------------------------------
303//SUM OF SQUARES-------------------------------------------------------------------------------------------------------------------------
304
305        private double getSumOfSquares(String c, int s)
306        {
307            String shifted = "";
308            //Shiften....
309            shifted = getShift(c, s);
310
311            //frequency ermitteln
312            OF = observedFrequency(shifted);
313
314
315            double sum = 0;
316            double help;
317            //Sum ermitteln
318            for (int letter = 0; letter < alphabet.Length; letter++)
319            {
320                help = (EF[alphabet[letter]] / 100) - OF[alphabet[letter]];
321
322                sum = sum + (help * help);
323
324            }
325
326            return sum;
327        }
328
329//---------------------------------------------------------------------------------------------------------------------------------------
330//LETTER TO NUMBER----------------------------------------------------------------------------------------------------------------------
331
332        private int getPos(char c)
333        {
334            int pos = -1;
335            for (int i = 0; i < alphabet.Length; i++)
336            {
337                if (alphabet[i] == c)
338                {
339                    pos = i;
340                }
341            }
342            return pos;
343        }
344
345//---------------------------------------------------------------------------------------------------------------------------------------
346//SHIFT PART-----------------------------------------------------------------------------------------------------------------------------
347
348        private String getShift(String c, int s)
349        {
350            String shifted = "";
351            int gotcha = s;
352
353            for (int x = 0; x < c.Length; x++)
354            {
355
356                gotcha = (getPos(c[x]) - gotcha + 26) % 26;
357                shifted = shifted + alphabet[gotcha];
358            }
359
360            return shifted;
361
362        }
363
364
365//---------------------------------------------------------------------------------------------------------------------------------------       
366//FREQUENCY ANALYSE PHASE----------------------------------------------------------------------------------------------------------------
367       
368       
369        private double[] observedFrequency(String c)
370        {
371            double[] book = new double[255];    //ASCII Buch merkt sich Anzahl
372
373            for (int x = 0; x < c.Length; x++)  //für jeden buchstaben in er ciphercolumn
374            {
375                book[(int)c[x]]++;
376            }
377
378            for (int y = 0; y < book.Length; y++)  //die frequenz ermitteln
379            {
380                book[y] = book[y] / c.Length;
381            }
382
383            return book;
384        }
385
386
387        private double[] expectedFrequency(int l)
388        {
389            double[] book = new double[255];    //ASCII Buch merkt sich Anzahl
390            double[] languagefrequency;
391
392            switch (l)
393            {
394                case 0: //English
395                    languagefrequency = new double[] { 8.167, 1.492, 2.782, 4.253, 12.702, 2.228, 2.015, 6.094, 6.966, 0.153, 0.772, 4.025, 2.406, 6.749, 7.507, 1.929, 0.095, 5.987, 6.327, 9.056, 2.758, 0.978, 2.360, 0.150, 1.974, 0.074 };
396                    break;
397                case 1: //German
398                    languagefrequency = new double[] { 6.51, 1.89, 3.06, 5.08, 17.40, 1.66, 3.01, 4.76, 7.55, 0.27, 1.21, 3.44, 2.53, 9.78, 2.51, 0.79, 0.02, 7.00, 7.27, 6.15, 4.35, 0.67, 1.89, 0.03, 0.04, 1.13 };
399                    break;
400                case 2: //French
401                    languagefrequency = new double[] { 7.636, 0.901, 3.260, 3.669, 14.715, 1.066, 0.866, 0.737, 7.529, 0.545, 0.049, 5.456, 2.968, 7.095, 5.378, 3.021, 1.362, 6.553, 7.948, 7.244, 6.311, 1.628, 0.114, 0.387, 0.308, 0.136 };
402                    break;
403                case 3: //Spain
404                    languagefrequency = new double[] { 12.53, 1.42, 4.68, 5.86, 13.68, 0.69, 1.01, 0.70, 6.25, 0.44, 0.01, 4.97, 3.15, 6.71, 8.68, 2.51, 0.88, 6.87, 7.98, 4.63, 3.93, 0.90, 0.02, 0.22, 0.90, 0.52 };
405                    break;
406                default: //English
407                    languagefrequency = new double[] { 8.167, 1.492, 2.782, 4.253, 12.702, 2.228, 2.015, 6.094, 6.966, 0.153, 0.772, 4.025, 2.406, 6.749, 7.507, 1.929, 0.095, 5.987, 6.327, 9.056, 2.758, 0.978, 2.360, 0.150, 1.974, 0.074 };
408                    break;
409            }
410
411            for (int c = 0; c < 26; c++)
412            {
413                book[(int)alphabet[c]] = languagefrequency[c];
414            }
415
416            return book;
417        }
418
419
420//-----------------------------------------------------------------------------------------------------------------------------------------
421
422        #endregion
423
424        #region Event Handling
425
426        public event StatusChangedEventHandler OnPluginStatusChanged;
427
428        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
429
430        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
431
432        public event PropertyChangedEventHandler PropertyChanged;
433
434        private void GuiLogMessage(string message, NotificationLevel logLevel)
435        {
436            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
437        }
438
439        private void OnPropertyChanged(string name)
440        {
441            EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
442        }
443
444        private void ProgressChanged(double value, double max)
445        {
446            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
447        }
448
449        #endregion
450    }
451}
Note: See TracBrowser for help on using the repository browser.