source: trunk/CrypPlugins/Vigenere/Vigenere.cs @ 1444

Last change on this file since 1444 was 1444, checked in by nolte, 12 years ago

Expanded the Vigenere plugin with a full working autokey modus

File size: 16.8 KB
Line 
1/*
2   Copyright 2008 Sebastian Przybylski, University of Siegen
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*/
16
17using System;
18using System.Collections.Generic;
19using System.Linq;
20using System.Text;
21using Cryptool.PluginBase;
22using System.IO;
23using System.ComponentModel;
24using Cryptool.PluginBase.Cryptography;
25using Cryptool.PluginBase.IO;
26
27namespace Cryptool.Vigenere
28{
29    [Author("Sebastian Przybylski", "sebastian@przybylski.org", "Uni-Siegen", "http://www.uni-siegen.de")]
30    [PluginInfo(false, "VigenÚre", "VigenÚre -- classic or autokey polyalphabetic substitution cipher", "Vigenere/DetailedDescription/Description.xaml",
31      "Vigenere/Images/icon.png", "Vigenere/Images/encrypt.png", "Vigenere/Images/decrypt.png")]
32    [EncryptionType(EncryptionType.Classic)]
33    public class Vigenere : IEncryption
34    {
35        #region Private variables
36
37        private VigenereSettings settings;
38        private CryptoolStream outputData;
39        private string inputString;
40        private string outputString;
41        private char[] keyword;
42        private enum VigenereMode { encrypt, decrypt, autoencrypt, autodecrypt };
43        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
44
45        #endregion
46
47        #region Public interface
48
49        /// <summary>
50        /// Constructor
51        /// </summary>
52        public Vigenere()
53        {
54            this.settings = new VigenereSettings();
55            ((VigenereSettings)(this.settings)).LogMessage += Vigenere_LogMessage;
56        }
57
58        /// <summary>
59        /// Get or set all settings for this algorithm
60        /// </summary>
61        public ISettings Settings
62        {
63            get { return this.settings; }
64            set { this.settings = (VigenereSettings)value; }
65        }
66
67        [PropertyInfo(Direction.OutputData, "Stream output", "The string after processing with the VigenÚre cipher is converted to a stream.Default encoding is used.", null, false, false, DisplayLevel.Beginner,QuickWatchFormat.Text, null)]
68        public CryptoolStream OutputData
69        {
70            get
71            {
72                if (outputString != null)
73                {
74                    CryptoolStream cs = new CryptoolStream();
75                    listCryptoolStreamsOut.Add(cs);
76                    cs.OpenRead(this.GetPluginInfoAttribute().Caption, Encoding.Default.GetBytes(outputString.ToCharArray()));
77                    return cs;
78                }
79                else
80                {
81                    return null;
82                }
83            }
84            set { }
85        }
86
87        [PropertyInfo(Direction.InputData, "Text input", "Input a string to be processed by the VigenÚre cipher", null, true, false, DisplayLevel.Beginner,QuickWatchFormat.Text, null)]
88        public string InputString
89        {
90            get { return this.inputString; }
91            set
92            {
93                if (value != inputString)
94                {
95                    this.inputString = value;
96                    OnPropertyChanged("InputString");
97                }
98            }
99        }
100
101        [PropertyInfo(Direction.OutputData,"Text output", "The string after processing with the VigenÚre cipher", null, false, false, DisplayLevel.Beginner,QuickWatchFormat.Text, null)]
102        public string OutputString
103        {
104            get { return this.outputString; }
105            set
106            {
107                outputString = value;
108                OnPropertyChanged("OutputString");
109            }
110        }
111
112        [PropertyInfo(Direction.InputData, "External alphabet input", "Input a string containing the alhabet which should be used by VigenÚre. If no alphabet is provided on this input, the internal alphabet will be used.", null, false, false, DisplayLevel.Expert,QuickWatchFormat.Text, null)]
113        public string InputAlphabet
114        {
115            get { return ((VigenereSettings)this.settings).AlphabetSymbols; }
116            set
117            {
118                if (value != null && value != settings.AlphabetSymbols) 
119                { 
120                    ((VigenereSettings)this.settings).AlphabetSymbols = value;
121                    OnPropertyChanged("InputAlphabet");
122                }
123            }
124        }
125        [PropertyInfo(Direction.InputData, "String", "Keyword as derived by the VigenereAnalyser", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
126        public string ShiftValue
127        {
128            get { return settings.ShiftChar; }
129            set
130            {
131                if (value != settings.ShiftChar)
132                {
133                    settings.ShiftChar=value;
134                    OnPropertyChanged("ShiftValue");
135
136                }
137            }
138        }
139
140        /// <summary>
141        /// Vigenere encryption
142        /// </summary>
143        public void Encrypt()
144        {
145            ProcessVigenere(VigenereMode.encrypt);
146        }
147
148        public void AutoKeyEncrypt()
149        {
150            ProcessVigenere(VigenereMode.autoencrypt);
151        }
152
153        /// <summary>
154        /// Vigenere decryption
155        /// </summary>
156        public void Decrypt()
157        {
158            ProcessVigenere(VigenereMode.decrypt);
159        }
160
161        public void AutoKeyDecrypt()
162        {
163            ProcessVigenere(VigenereMode.autodecrypt);
164        }
165
166        #endregion
167
168        #region IPlugin members
169        public void Initialize()
170        {
171        }
172
173        public void Dispose()
174        {
175            foreach (CryptoolStream stream in listCryptoolStreamsOut)
176            {
177                stream.Close();
178            }
179            listCryptoolStreamsOut.Clear();
180        }
181
182        public bool HasChanges
183        {
184            get { return settings.HasChanges; }
185            set { settings.HasChanges = value; }
186        }
187
188        /// <summary>
189        /// Fire if progress bar status was changed
190        /// </summary>
191        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
192
193        /// <summary>
194        /// Fire if a new message has to be shown in the status bar
195        /// </summary>
196        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
197
198        public System.Windows.Controls.UserControl Presentation
199        {
200            get { return null; }
201        }
202
203        public System.Windows.Controls.UserControl QuickWatchPresentation
204        {
205            get { return null; }
206        }
207
208        public void Stop()
209        {
210        }
211
212        public void PostExecution()
213        {
214            Dispose();
215        }
216
217        public void PreExecution()
218        {
219            Dispose();
220        }
221
222        #endregion
223
224        #region INotifyPropertyChanged Members
225
226        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
227
228        public void OnPropertyChanged(string name)
229        {
230            if (PropertyChanged != null)
231            {
232                PropertyChanged(this, new PropertyChangedEventArgs(name));
233            }
234        }
235
236        #endregion
237
238
239
240        #region Private methods
241
242        /// <summary>
243        /// Does the actual Vigenere processing, i.e. encryption or decryption
244        /// </summary>
245        /// <param name="mode"></param>
246        private void ProcessVigenere(VigenereMode mode)
247        {
248            VigenereSettings cfg = (VigenereSettings)this.settings;
249            StringBuilder output = new StringBuilder(String.Empty);
250            string alphabet = cfg.AlphabetSymbols;
251            int autopos = 0;
252
253            if (!cfg.CaseSensitiveAlphabet)
254            {
255                alphabet = cfg.AlphabetSymbols.ToUpper();
256            }
257            if (inputString != null)
258            {
259                int shiftPos = 0;
260                for (int i = 0; i < inputString.Length; i++)
261                {
262                    //get plaintext char which is currently processed
263                    char currentChar = inputString[i];
264
265                    //remember if it is upper case (ohterwise lowercase is assumed)
266                    bool uppercase = char.IsUpper(currentChar);
267                   
268                    //get the position of the plaintext character in the alphabet
269                    int ppos = 0;
270                    if (cfg.CaseSensitiveAlphabet)
271                    {
272                        ppos = alphabet.IndexOf(currentChar);
273                    }
274                    else
275                    {
276                        ppos = alphabet.IndexOf(char.ToUpper(currentChar));
277                    }
278
279                    if (ppos >= 0)
280                    {
281
282                        //found the plaintext character in the alphabet, begin shifting
283                        int cpos = 0;
284                        switch (mode)
285                        {
286                            case VigenereMode.encrypt:
287
288                                cpos = (ppos + cfg.ShiftKey[shiftPos]) % alphabet.Length;
289
290                                //inkrement shiftPos to map inputString whith all keys
291                                //if shiftPos > ShiftKey.Length, begin again at the beginning
292                                shiftPos++;
293                                if (shiftPos >= cfg.ShiftKey.Length) shiftPos = 0;
294                                break;
295                           
296                            case VigenereMode.decrypt:
297
298                                cpos = (ppos - cfg.ShiftKey[shiftPos] + alphabet.Length) % alphabet.Length;
299                               
300                                //inkrement shiftPos to map inputString whith all keys
301                                //if shiftPos > ShiftKey.Length, begin again at the beginning
302                                shiftPos++;
303                                if (shiftPos >= cfg.ShiftKey.Length) shiftPos = 0;
304                                break;
305
306                            case VigenereMode.autoencrypt:
307
308                                //key still used
309                                if (shiftPos < cfg.ShiftKey.Length)
310                                {
311                                    cpos = (ppos + cfg.ShiftKey[shiftPos]) % alphabet.Length;
312                                    shiftPos++;
313                                }
314                                else //using plaintext
315                                {
316                                    //taking the plaintextchar from the next position
317                                    int pkey = alphabet.IndexOf(char.ToUpper(inputString[autopos]));
318                                    //check if the next plaintextchar is in the alphabet
319                                    while (pkey < 0)
320                                    {
321                                        autopos++;
322                                        pkey = alphabet.IndexOf(char.ToUpper(inputString[autopos]));
323                                    }
324
325                                    cpos = (ppos + pkey) % alphabet.Length;
326                                    autopos++;
327                                }
328                                break;
329
330                            case VigenereMode.autodecrypt:
331
332                                //key still used
333                                if (shiftPos < cfg.ShiftKey.Length)
334                                {
335                                    cpos = (ppos - cfg.ShiftKey[shiftPos] + alphabet.Length) % alphabet.Length;
336                                    shiftPos++;
337                                }
338                                else //using plaintext
339                                {
340                                    outputString = output.ToString();
341
342                                    //taking the deciphered plaintextchar from the next position
343                                    int pkey = alphabet.IndexOf(char.ToUpper(outputString[autopos]));
344                                    //check if the next deciphered plaintextchar is in the alphabet
345                                    while (pkey < 0)
346                                    {
347                                        autopos++;
348                                        pkey = alphabet.IndexOf(char.ToUpper(outputString[autopos]));
349                                    }
350
351                                    cpos = (ppos - pkey + alphabet.Length) % alphabet.Length;
352                                    autopos++;
353                                }
354                                break;
355                        }
356
357                                                 
358                        //we have the position of the ciphertext character, now we have to output it in the right case
359                        if (cfg.CaseSensitiveAlphabet)
360                        {
361                            output.Append(alphabet[cpos]);
362                        }
363                        else
364                        {
365                            if (uppercase)
366                            {
367                                output.Append(char.ToUpper(alphabet[cpos]));
368                            }
369                            else
370                            {
371                                output.Append(char.ToLower(alphabet[cpos]));
372                            }
373                        }
374                    }
375                    else
376                    {
377                        //the plaintext character was not found in the alphabet, begin handling with unknown characters
378                        switch ((VigenereSettings.UnknownSymbolHandlingMode)cfg.UnknownSymbolHandling)
379                        {
380                            case VigenereSettings.UnknownSymbolHandlingMode.Ignore:
381                                output.Append(inputString[i]);
382                                break;
383                            case VigenereSettings.UnknownSymbolHandlingMode.Replace:
384                                output.Append('?');
385                                break;
386                        }
387                    }
388
389                    //show the progress
390                    if (OnPluginProgressChanged != null)
391                    {
392                        OnPluginProgressChanged(this, new PluginProgressEventArgs(i, inputString.Length - 1));
393                    }
394                }
395                outputString = output.ToString();
396                OnPropertyChanged("OutputString");
397                OnPropertyChanged("OutputData");
398            }
399        }
400
401        /// <summary>
402        /// Handles log messages from the settings class
403        /// </summary>
404        /// <param name="sender"></param>
405        /// <param name="msg"></param>
406        /// <param name="logeLevel"></param>
407        private void Vigenere_LogMessage(string msg, NotificationLevel logLevel)
408        {
409            if (OnGuiLogNotificationOccured != null)
410            {
411                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(msg, this, logLevel));
412            }
413        }
414
415        #endregion
416
417        #region IPlugin Members
418
419#pragma warning disable 67
420                                public event StatusChangedEventHandler OnPluginStatusChanged;
421#pragma warning restore
422
423        public void Execute()
424        {
425           switch (settings.Modus)
426           {
427               //Classic Modus
428               case 0:
429
430                    switch (settings.Action)
431                    {
432                        case 0:
433                            Encrypt();
434                            break;
435                        case 1:
436                            Decrypt();
437                            break;
438                        default:
439                            break;
440                    }
441                    break;
442
443               //Autokey Modus
444               case 1:
445
446                    switch (settings.Action)
447                    {
448                        case 0:
449                            AutoKeyEncrypt();
450                            break;
451                        case 1:
452                            AutoKeyDecrypt();
453                            break;
454                        default:
455                            break;
456                    }
457                    break;
458       
459            }
460       
461        }
462
463        public void Pause()
464        {
465
466        }
467
468        #endregion
469
470    }
471}
Note: See TracBrowser for help on using the repository browser.