source: trunk/CrypPlugins/Playfair/Playfair.cs @ 1778

Last change on this file since 1778 was 1256, checked in by Matthäus Wander, 12 years ago

Playfair:

  • fixed preformatting to be consistent with literature (e.g. William Stallings: Cryptography and Network Security (page 44); F. L. Bauer: Entzifferte Geheimnisse (page 66))
  • closes #133
  • fixed another issue (last character insertion)
File size: 14.9 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.Collections;
23using System.IO;
24using Cryptool.PluginBase.Cryptography;
25using Cryptool.PluginBase.IO;
26using System.Windows.Controls;
27using System.ComponentModel;
28
29namespace Cryptool.Playfair
30{
31    [Author("Sebastian Przybylski","sebastian@przybylski.org","Uni Siegen","http://www.uni-siegen.de")]
32    [PluginInfo(false, "Playfair", "Playfair -- classic digraph substitution cipher", "Playfair/DetailedDescription/Description.xaml",
33      "Playfair/Images/icon.png", "Playfair/Images/encrypt.png", "Playfair/Images/decrypt.png")]
34    [EncryptionType(EncryptionType.Classic)]
35    public class Playfair : IEncryption
36    {
37        #region Private variables
38
39        private PlayfairSettings settings;
40        private string inputString;
41        private string outputString;
42        private string preFormatedInputString;
43        private int matrixSize;
44        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
45
46        #endregion
47
48        #region Public interface
49
50        /// <summary>
51        /// Constructor
52        /// </summary>
53        public Playfair()
54        {
55            this.settings = new PlayfairSettings();
56            ((PlayfairSettings)(this.settings)).LogMessage += Playfair_LogMessage;
57        }
58
59        /// <summary>
60        /// Get or set all settings for this algorithm
61        /// </summary>
62        public ISettings Settings
63        {
64            get { return (ISettings)this.settings; }
65            set { this.settings = (PlayfairSettings)value; }
66        }
67
68        [PropertyInfo(Direction.OutputData,"Stream output","The string after processing with the Playfair cipher is converted to a stream. Default encoding is used.","",false,false, DisplayLevel.Beginner,QuickWatchFormat.Text, null)]
69        public CryptoolStream OutputData
70        {
71            get
72            {
73                if (outputString != null)
74                {
75                    CryptoolStream cs = new CryptoolStream();
76                    listCryptoolStreamsOut.Add(cs);
77                    cs.OpenRead(this.GetPluginInfoAttribute().Caption, Encoding.Default.GetBytes(outputString.ToCharArray()));
78                    return cs;
79                }
80                else
81                {
82                    return null;
83                }
84            }
85            set { }
86        }
87
88        [PropertyInfo(Direction.InputData,"Text input","Input a string to be processed by the Playfair cipher","",true,false,DisplayLevel.Beginner,QuickWatchFormat.Text, null)]
89        public string InputString
90        {
91            get { return this.inputString; }
92            set
93            {
94                if (value != inputString)
95                {
96                    this.inputString = value;
97                    OnPropertyChanged("InputString");
98                }
99            }
100        }
101
102        [PropertyInfo(Direction.OutputData,"Pre-formated input string","If Pre-format text option is enabled the input string is confined to the alphabet used.",null,false,false,DisplayLevel.Beginner,QuickWatchFormat.Text,null)]
103        public string PreFormatedInputString
104        {
105            get { return this.preFormatedInputString; }
106            set
107            {
108                preFormatedInputString = value;
109                OnPropertyChanged("PreFormatedInputString");
110            }
111        }
112
113        [PropertyInfo(Direction.OutputData,"Text output","The string after processing with the Playfair cipher","",false,false,DisplayLevel.Beginner,QuickWatchFormat.Text, null)]
114        public string OutputString
115        {
116            get { return this.outputString; }
117            set
118            {
119                outputString = value;
120                OnPropertyChanged("OutputString");
121            }
122        }
123
124
125        /// <summary>
126        /// Playfair encryption
127        /// </summary>
128        public void Encrypt()
129        {
130            if (inputString != null)
131            {
132                StringBuilder output = new StringBuilder(string.Empty);
133                //set selected matrix size
134                if (settings.MatrixSize == 0) matrixSize = 5;
135                else matrixSize = 6;
136
137                //pre-format input text, if user activated this property
138                if (settings.PreFormatText)
139                    preFormatedInputString = preFormatText();
140                else
141                    preFormatedInputString = inputString;
142                OnPropertyChanged("PreFormatedInputString");
143
144                //begin the encryption
145                for (int i = 0; i < preFormatedInputString.Length - 1; i++)
146                {
147                    int indexCh1 = settings.AlphabetMatrix.IndexOf(preFormatedInputString[i]);
148                    i++;
149                    int indexCh2 = settings.AlphabetMatrix.IndexOf(preFormatedInputString[i]);
150
151                    //first, get new char index from cipher alphabet
152                    int newIndexCh1;
153                    int newIndexCh2;
154
155                    int rowCh1 = indexCh1 / matrixSize;
156                    int rowCh2 = indexCh2 / matrixSize;
157                    int colCh1 = indexCh1 % matrixSize;
158                    int colCh2 = indexCh2 % matrixSize;
159
160                    if (rowCh1 == rowCh2)
161                    {
162                        newIndexCh1 = getRightNeighbour(indexCh1);
163                        newIndexCh2 = getRightNeighbour(indexCh2);
164                    }
165                    else if (colCh1 == colCh2)
166                    {
167                        newIndexCh1 = getLowerNeighbour(indexCh1);
168                        newIndexCh2 = getLowerNeighbour(indexCh2);
169                    }
170                    else
171                    {
172                        newIndexCh1 = getSubstitute(rowCh1, colCh2);
173                        newIndexCh2 = getSubstitute(rowCh2, colCh1);
174                    }
175                    output.Append(settings.AlphabetMatrix[newIndexCh1]);
176                    output.Append(settings.AlphabetMatrix[newIndexCh2]);
177                }
178                outputString = output.ToString();
179                OnPropertyChanged("OutputString");
180                OnPropertyChanged("OutputData");
181
182            }
183        }
184
185        /// <summary>
186        /// Playfair decryption
187        /// </summary>
188        public void Decrypt()
189        {
190            if (inputString != null)
191            {
192                StringBuilder output = new StringBuilder(string.Empty);
193                //set selected matrix size
194                if (settings.MatrixSize == 0) matrixSize = 5;
195                else matrixSize = 6;
196
197                // Decryption does not require preformat, otherwise the ciphertext format is wrong
198                // We attempt to preformat nevertheless.
199
200                //pre-format input text, if user activated this property
201                if (settings.PreFormatText)
202                    preFormatedInputString = preFormatText();
203                else
204                    preFormatedInputString = inputString;
205                OnPropertyChanged("PreFormatedInputString");
206
207                //begin the encryption
208                for (int i = 0; i < preFormatedInputString.Length - 1; i++)
209                {
210                    int indexCh1 = settings.AlphabetMatrix.IndexOf(preFormatedInputString[i]);
211                    i++;
212                    int indexCh2 = settings.AlphabetMatrix.IndexOf(preFormatedInputString[i]);
213
214                    //first, get new char index from cipher alphabet
215                    int newIndexCh1;
216                    int newIndexCh2;
217
218                    int rowCh1 = indexCh1 / matrixSize;
219                    int rowCh2 = indexCh2 / matrixSize;
220                    int colCh1 = indexCh1 % matrixSize;
221                    int colCh2 = indexCh2 % matrixSize;
222
223                    if (rowCh1 == rowCh2)
224                    {
225                        newIndexCh1 = getLeftNeighbour(indexCh1);
226                        newIndexCh2 = getLeftNeighbour(indexCh2);
227                    }
228                    else if (colCh1 == colCh2)
229                    {
230                        newIndexCh1 = getUpperNeighbour(indexCh1);
231                        newIndexCh2 = getUpperNeighbour(indexCh2);
232                    }
233                    else
234                    {
235                        newIndexCh1 = getSubstitute(rowCh1, colCh2);
236                        newIndexCh2 = getSubstitute(rowCh2, colCh1);
237                    }
238                    output.Append(settings.AlphabetMatrix[newIndexCh1]);
239                    output.Append(settings.AlphabetMatrix[newIndexCh2]);
240                }
241                outputString = output.ToString();
242                OnPropertyChanged("OutputString");
243                OnPropertyChanged("OutputData");
244
245            }
246        }
247
248
249        #endregion
250
251        #region IPlugin members
252
253        public void Initialize()
254        {
255
256        }
257
258        public void Dispose()
259        {
260            foreach (CryptoolStream stream in listCryptoolStreamsOut)
261            {
262                stream.Close();
263            }
264            listCryptoolStreamsOut.Clear();
265        }
266
267        public bool HasChanges
268        {
269            get { return settings.HasChanges; }
270            set { settings.HasChanges = value; }
271        }
272
273        /// <summary>
274        /// Fire, if status has to be shown in the progress bar
275        /// </summary>
276#pragma warning disable 67
277                                public event StatusChangedEventHandler OnPluginStatusChanged;
278#pragma warning restore
279       
280
281        /// <summary>
282        /// Fire, if a message has to be shonw in the status bar
283        /// </summary>
284        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
285
286        public UserControl Presentation
287        {
288            get { return null; }
289        }
290
291        public UserControl QuickWatchPresentation
292        {
293            get { return null; }
294        }
295
296        public void Stop()
297        {
298        }
299
300        public void PreExecution()
301        {
302            Dispose();
303        }
304
305        public void PostExecution()
306        {
307            Dispose();
308        }
309
310        #endregion
311
312        #region INotifyPropertyChanged Members
313
314        public event PropertyChangedEventHandler PropertyChanged;
315
316        public void OnPropertyChanged(string name)
317        {
318            if (PropertyChanged != null)
319            {
320                PropertyChanged(this, new PropertyChangedEventArgs(name));
321            }
322        }
323
324        #endregion
325
326        #region Private methods
327
328        private int getRightNeighbour(int index)
329        {
330            if (index % matrixSize < matrixSize - 1) index++;
331            else if (index % matrixSize == matrixSize - 1) index = index - 4;
332            else index = -1;
333
334            return index;
335        }
336
337        private int getLowerNeighbour(int index)
338        {
339            if (index + 5 < settings.AlphabetMatrix.Length) index = index + matrixSize;
340            else index = (index + matrixSize) % settings.AlphabetMatrix.Length;
341
342            return index;
343        }
344
345        private int getUpperNeighbour(int index)
346        {
347            if (index < matrixSize) index = settings.AlphabetMatrix.Length - (matrixSize - index);
348            else index = index - matrixSize;
349
350            return index;
351        }
352
353        private int getLeftNeighbour(int index)
354        {
355            if (index % matrixSize > 0) index--;
356            else index = index + matrixSize - 1;
357
358            return index;
359        }
360
361        private int getSubstitute(int row, int col)
362        {
363            return matrixSize * row + col;
364        }
365
366        private string preFormatText()
367        {
368            StringBuilder sb = new StringBuilder();
369
370            //remove or replace nonalphabet char
371            for (int i = 0; i < inputString.Length; i++)
372            {
373                char c = char.ToUpper(inputString[i]);
374
375                if (settings.AlphabetMatrix.Contains(c))
376                {
377                    sb.Append(c);
378                }
379                else
380                {
381                    if (c == 'J') sb.Append("I");
382                    if (c == 'Ä') sb.Append("A");
383                    if (c == 'Ö') sb.Append("O");
384                    if (c == 'Ü') sb.Append("U");
385                }
386            }
387
388            //if separate char is enabled begin with separating
389            if (settings.SeperatePairs)
390            {
391                for (int i = 0; i <= sb.Length-2; i+=2)
392                {
393                    if (sb[i] == sb[i + 1]) // same chars, insert X
394                    {
395                        if (sb[i] == settings.Separator) // avoid XX, use XY instead
396                            sb.Insert(i+1, settings.SeparatorReplacement);
397                        else
398                            sb.Insert(i+1, settings.Separator);
399                    }
400                }
401            }
402
403            // does the input end with a single letter?
404            if (sb.Length % 2 != 0)
405            {
406                if (sb[sb.Length-1] == settings.Separator) // avoid XX, use XY instead
407                    sb.Append(settings.SeparatorReplacement);
408                else
409                    sb.Append(settings.Separator);
410            }
411
412            return sb.ToString();
413        }
414
415        private void Playfair_LogMessage(string msg, NotificationLevel logLevel)
416        {
417            if (OnGuiLogNotificationOccured != null)
418            {
419                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(msg, this, logLevel));
420            }
421        }
422
423        #endregion
424
425        #region IPlugin Members
426
427#pragma warning disable 67
428        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
429#pragma warning restore
430
431        public void Execute()
432        {
433            switch (settings.Action)
434            {
435                case 0:
436                    Encrypt();
437                    break;
438                case 1:
439                    Decrypt();
440                    break;
441                default:
442                    break;
443            }
444        }
445
446        public void Pause()
447        {
448        }
449
450        #endregion
451    }
452}
Note: See TracBrowser for help on using the repository browser.