source: trunk/CrypPlugins/SDES/SDES.cs @ 743

Last change on this file since 743 was 743, checked in by kopal, 12 years ago

SDES presentation finished

File size: 71.0 KB
Line 
1/*                             
2   Copyright 2009 Team CrypTool (Sven Rech,Dennis Nolte,Raoul Falk,Nils Kopal), Uni Duisburg-Essen
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 System.IO;
21using System.Security.Cryptography;
22using Cryptool.PluginBase;
23using System.ComponentModel;
24using Cryptool.PluginBase.Cryptography;
25using Cryptool.PluginBase.IO;
26using System.Windows.Controls;
27using Cryptool.PluginBase.Control;
28using System.Threading;
29using System.Windows.Threading;
30using System.Runtime.InteropServices;
31
32namespace Cryptool.Plugins.Cryptography.Encryption
33{
34    /// <summary>
35    /// This plugin encrypts / decrypts texts with the simplified DES alogrithm (SDES)
36    /// It can be used as plugin in a normal encryption/decryption chanin or be
37    /// used by the KeySearcher to do bruteforcing
38    /// </summary>
39    [Author("Nils Kopal", "nils.kopal@cryptool.de", "Uni Duisburg", "http://www.uni-duisburg-essen.de")]
40    [PluginInfo(false, "SDES", "Simplified Data Encryption Standard", "SDES/DetailedDescription/Description.xaml", "SDES/icon.png", "SDES/Images/encrypt.png", "SDES/Images/decrypt.png")]
41    [EncryptionType(EncryptionType.SymmetricBlock)]
42    public class SDES : IEncryption
43    {
44        #region Private variables
45
46        private SDESSettings settings;
47        private CryptoolStream inputStream;
48        private CryptoolStream outputStream;
49        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
50        private byte[] inputKey;
51        private byte[] inputIV;       
52        private bool stop = false;
53        private UserControl presentation = new SDESPresentation();
54        private SDESControl controlSlave;
55
56        #endregion
57
58        #region events
59
60        public event PropertyChangedEventHandler PropertyChanged;
61        public event StatusChangedEventHandler OnPluginStatusChanged;
62        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
63        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
64
65        #endregion
66
67        #region public
68
69        /// <summary>
70        /// Tells you wether input changed or not
71        /// </summary>
72        public bool InputChanged
73        { get; set; }
74
75        /// <summary>
76        /// Constructs a new SDES
77        /// </summary>
78        public SDES()
79        {
80            InputChanged = false;
81            this.settings = new SDESSettings();
82            this.settings.OnPluginStatusChanged += settings_OnPluginStatusChanged;
83        }
84
85        /// <summary>       
86        /// The status of the plugin changes
87        /// </summary>
88        /// <param name="sender"></param>
89        /// <param name="args"></param>
90        void settings_OnPluginStatusChanged(IPlugin sender, StatusEventArgs args)
91        {
92            if(OnPluginStatusChanged != null)OnPluginStatusChanged(this, args);
93        }
94
95        /// <summary>
96        /// Sets/Gets the settings of this plugin
97        /// </summary>
98        public ISettings Settings
99        {
100            get { return this.settings; }
101            set { this.settings = (SDESSettings)value; }
102        }
103   
104        /// <summary>
105        /// Is this Plugin in Status stop?
106        /// </summary>
107        /// <returns></returns>
108        public bool getStop()
109        {
110            return stop;
111        }
112
113        /// <summary>
114        /// Gets/Sets the input of the SDES plugin (the text which should be encrypted/decrypted)
115        /// </summary>
116        [PropertyInfo(Direction.InputData, "Input", "Data to be encrypted or decrypted", null, true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
117        public CryptoolStream InputStream
118        {
119            get 
120            {
121                try
122                {
123                    if (inputStream != null)
124                    {
125                        CryptoolStream cs = new CryptoolStream();
126                        cs.OpenRead(inputStream.FileName);
127                        listCryptoolStreamsOut.Add(cs);
128                        return cs;
129                    }
130                    else return null;
131                }
132                catch (Exception ex)
133                {
134                    GuiLogMessage("getInputStream: " + ex.Message, NotificationLevel.Error);
135                    return null;
136                }
137
138            }
139            set 
140            {
141                this.inputStream = value;
142                if (value != null)
143                {
144                    listCryptoolStreamsOut.Add(value);                     
145                }
146                OnPropertyChanged("InputStream");
147            }
148        }
149
150        /// <summary>
151        /// Gets/Sets the output of the SDES plugin (the text which is encrypted/decrypted)
152        /// </summary>
153        [PropertyInfo(Direction.OutputData, "Output stream", "Encrypted or decrypted output data", null, true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
154        public CryptoolStream OutputStream
155        {
156            get
157            {
158                try
159                {
160                    if (this.outputStream != null)
161                    {
162                        CryptoolStream cs = new CryptoolStream();
163                        listCryptoolStreamsOut.Add(cs);
164                        cs.OpenRead(this.outputStream.FileName);
165                        return cs;
166                    }
167                    return null;
168                }
169                catch (Exception ex)
170                {
171                    GuiLogMessage("getOutputStream: " + ex.Message, NotificationLevel.Error);
172                    return null;
173                }
174            }
175            set
176            {
177
178                this.outputStream = value;
179                if (value != null)
180                {
181                    listCryptoolStreamsOut.Add(value);
182                }
183                OnPropertyChanged("OutputStream");
184            }
185        }
186
187        /// <summary>
188        /// Gets/Sets the key which should be used.Must be 10 bytes  (only 1 or 0 allowed).
189        /// </summary>
190        [PropertyInfo(Direction.InputData, "Key", "Must be 8 bytes (only 1 or 0 allowed).", null, true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
191        public byte[] InputKey
192        {
193            get { return this.inputKey; }
194            set
195            {
196                InputChanged = true;
197                this.inputKey = value;
198                OnPropertyChanged("InputKey");
199            }
200        }
201
202        /// <summary>
203        /// Gets/Sets the Initialization Vector which should be used.Must be 10 bytes  (only 1 or 0 allowed).
204        /// </summary>
205        [PropertyInfo(Direction.InputData, "IV", "IV to be used in chaining modes, must be 10 bytes (only 1 or 0 allowed).", null, true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
206        public byte[] InputIV
207        {
208            get { return this.inputIV; }
209            set
210            {
211                this.inputIV = value;
212                OnPropertyChanged("InputIV");
213            }
214        }
215
216        /// <summary>
217        /// Start encrypting
218        /// </summary>
219        public void Encrypt()
220        {
221            //Encrypt Stream
222            process(0);
223        }
224
225        /// <summary>
226        /// Start decrypting
227        /// </summary>
228        public void Decrypt()
229        {
230            //Decrypt Stream
231            process(1);
232        }
233
234        /// <summary>
235        /// Called by the environment to start this plugin
236        /// </summary>
237        public void Execute()
238        {
239            process(settings.Action);
240        }
241
242
243        /// <summary>
244        /// Get the Presentation of this plugin
245        /// </summary>
246        public UserControl Presentation
247        {
248            get { return this.presentation; }
249        }
250
251        /// <summary>
252        /// Get the QuickWatchPresentation of this plugin
253        /// </summary>
254        public UserControl QuickWatchPresentation
255        {
256            get { return null; }
257        }
258
259        /// <summary>
260        /// Called by the environment to do initialization
261        /// </summary>
262        public void Initialize()
263        {
264        }
265
266        /// <summary>
267        /// Called by the envorinment if this plugin is unloaded
268        /// closes all streams
269        /// </summary>
270        public void Dispose()
271        {
272            try
273            {
274                this.stop = false;
275                inputKey = null;
276                inputIV = null;
277
278                foreach (CryptoolStream stream in listCryptoolStreamsOut)
279                {
280                    stream.Close();
281                }
282                listCryptoolStreamsOut.Clear();
283
284                if (controlSlave != null)
285                    controlSlave.Dispose();
286
287            }
288            catch (Exception ex)
289            {
290                GuiLogMessage(ex.Message, NotificationLevel.Error);
291            }
292        }
293
294        /// <summary>
295        /// Called by the environment of this plugin to stop it
296        /// </summary>
297        public void Stop()
298        {
299            this.stop = true;
300        }
301
302        /// <summary>
303        /// Called by the environment of this plugin after execution
304        /// </summary>
305        public void PostExecution()
306        {
307            Dispose();
308        }
309
310        /// <summary>
311        /// Called by the environment of this plugin before execution
312        /// </summary>
313        public void PreExecution()
314        {
315            Dispose();
316        }
317
318        /// <summary>
319        /// A property of this plugin changed
320        /// </summary>
321        /// <param name="name">propertyname</param>
322        public void OnPropertyChanged(string name)
323        {
324            if (PropertyChanged != null)
325            {
326                PropertyChanged(this, new PropertyChangedEventArgs(name));
327            }
328        }
329
330        /// <summary>
331        /// Logs a message into the messages of crypttool
332        /// </summary>
333        /// <param name="message">message</param>
334        /// <param name="logLevel">logLevel</param>
335        public void GuiLogMessage(string message, NotificationLevel logLevel)
336        {
337            if (OnGuiLogNotificationOccured != null)
338            {
339                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, logLevel));
340            }
341        }
342
343        /// <summary>
344        /// Sets the current progess of this plugin
345        /// </summary>
346        /// <param name="value">value</param>
347        /// <param name="max">max</param>
348        public void ProgressChanged(double value, double max)
349        {
350            if (OnPluginProgressChanged != null)
351            {
352                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
353            }
354        }
355
356        /// <summary>
357        /// Called by the environment of this plugin if it is set to pause
358        /// </summary>
359        public void Pause()
360        {
361
362        }
363
364        /// <summary>
365        /// Sets/Gets the ControlSlave of this plugin
366        /// </summary>
367        [PropertyInfo(Direction.ControlSlave, "SDES Slave", "Direct access to SDES.", "", DisplayLevel.Beginner)]
368        public IControlEncryption ControlSlave
369        {
370            get
371            {
372                if (controlSlave == null)
373                    controlSlave = new SDESControl(this);
374                return controlSlave;
375            }
376        } 
377
378        #endregion public
379
380        #region private
381
382        /// <summary>
383        /// This method checks if the input stream is valid. If it is not valid it sets it to a dummy stream
384        /// (this funcionality is stolen from DES plugin ;) )
385        /// </summary>
386        private void checkForInputStream()
387        {
388            if (settings.Action == 0 && (inputStream == null || (inputStream != null && inputStream.Length == 0)))
389            {
390                //create some input
391                String dummystring = "Dummy string - no input provided - \"Hello SDES World\" - dummy string - no input provided!";
392                this.inputStream = new CryptoolStream();
393                this.inputStream.OpenRead(this.GetPluginInfoAttribute().Caption, Encoding.Default.GetBytes(dummystring.ToCharArray()));
394                // write a warning to the ouside word
395                GuiLogMessage("WARNING - No input provided. Using dummy data. (" + dummystring + ")", NotificationLevel.Warning);
396            }
397        }
398
399        /// <summary>
400        /// Checks if the Input key is not null and has length 10 and only contains 1s and 0s
401        /// and if Input IV is not null and has length 8 and only contains 1s and 0s
402        /// </summary>
403        /// <returns>true if ok</returns>
404        private bool areKeyAndIVValid()
405        {
406
407            if (this.inputKey == null || this.inputKey.Length != 10)
408            {
409                GuiLogMessage("The Key has to have the length of 10 bytes (containing only '1' and '0')", NotificationLevel.Error);
410                return false;
411            }
412            if (this.inputIV == null || this.inputIV.Length != 8)
413            {
414                GuiLogMessage("The IV has to have the length of 8 bytes (containing only '1' and '0')", NotificationLevel.Error);
415                return false;
416            }
417
418            foreach (char character in inputKey)
419            {
420                if (character != '0' && character != '1')
421                {
422                    GuiLogMessage("Invalid character in Key: '" + character + "' - may only contain '1' and '0'", NotificationLevel.Error);
423                    return false;
424                }
425            }
426
427            foreach (char character in inputIV)
428            {
429                if (character != '0' && character != '1')
430                {
431                    GuiLogMessage("Invalid character in IV: '" + character + "' - may only contain '1' and '0'", NotificationLevel.Error);
432                    return false;
433                }
434            }
435
436            return true;
437        }
438
439        /// <summary>
440        /// Starts the encryption/decryption process with SDES
441        /// </summary>
442        /// <param name="action">0 = encrypt, 1 = decrypt</param>
443        private void process(int action)
444        {
445            if (controlSlave is object && InputStream is object && InputIV is object)
446            {
447                controlSlave.onStatusChanged();
448            }
449
450            try
451            {
452                checkForInputStream();
453                if (!areKeyAndIVValid())
454                {
455                    return;
456                }
457
458                if (inputStream == null || (inputStream != null && inputStream.Length == 0))
459                {
460                    GuiLogMessage("No input given. Not using dummy data in decrypt mode. Aborting now.", NotificationLevel.Error);
461                    return;
462                }
463
464                if (this.inputStream.CanSeek) this.inputStream.Position = 0;
465               
466                outputStream = new CryptoolStream();
467                listCryptoolStreamsOut.Add(outputStream);
468                outputStream.OpenWrite(this.GetPluginInfoAttribute().Caption);
469               
470                System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();               
471                DateTime startTime = DateTime.Now;
472
473                //Encrypt
474                if(action == 0){
475                   
476                    if (this.settings.Mode == 0)
477                    {
478                        GuiLogMessage("Starting encryption with ecb", NotificationLevel.Info);
479                        ElectronicCodeBook ecb = new ElectronicCodeBook(this);
480                        ecb.encrypt(inputStream, outputStream, Tools.stringToBinaryByteArray(enc.GetString(this.inputKey)));
481                    }
482                    else if (this.settings.Mode == 1)
483                    {
484                        GuiLogMessage("Starting encryption with cbc", NotificationLevel.Info);
485                        CipherBlockChaining cbc = new CipherBlockChaining(this);
486                        cbc.encrypt(inputStream, outputStream, Tools.stringToBinaryByteArray(enc.GetString(this.inputKey)), Tools.stringToBinaryByteArray(enc.GetString(this.inputIV)));
487                    }
488                }
489                //Decrypt
490                else if (action == 1)
491                {
492                                       
493                    if (this.settings.Mode == 0)
494                    {
495                        GuiLogMessage("Starting decryption with ecb", NotificationLevel.Info);
496                        ElectronicCodeBook ecb = new ElectronicCodeBook(this);
497                        ecb.decrypt(inputStream, outputStream, Tools.stringToBinaryByteArray(enc.GetString(this.inputKey)));
498                    }
499                    if (this.settings.Mode == 1)
500                    {
501                        GuiLogMessage("Starting decryption with cbc", NotificationLevel.Info);
502                        CipherBlockChaining cbc = new CipherBlockChaining(this);
503                        cbc.decrypt(inputStream, outputStream, Tools.stringToBinaryByteArray(enc.GetString(this.inputKey)), Tools.stringToBinaryByteArray(enc.GetString(this.inputIV)));
504                    }
505                }
506
507                DateTime stopTime = DateTime.Now;
508                TimeSpan duration = stopTime - startTime;
509                if (!stop)
510                {
511                    GuiLogMessage("En-/Decryption complete! ", NotificationLevel.Info);
512                    GuiLogMessage("Wrote data to file: " + outputStream.FileName, NotificationLevel.Info);
513                    GuiLogMessage("Time used: " + duration.ToString(), NotificationLevel.Debug);
514                    OnPropertyChanged("OutputStream");
515               
516                }else{                   
517                    GuiLogMessage("Aborted!", NotificationLevel.Info);
518                }
519
520                //avoid unnecessary error messages because of wrong input/output streams:
521                outputStream.Close();
522                outputStream = null;
523                inputStream.Close();
524                inputStream = null;
525            }
526            catch (Exception exception)
527            {
528                GuiLogMessage(exception.Message, NotificationLevel.Error);
529            }
530            finally
531            {             
532                ProgressChanged(1, 1);
533            }
534        }
535
536        #endregion
537
538    }//end SDES
539
540    /// <summary>
541    /// This Class is for controlling the SDES with a "brute forcer" like KeySearcher
542    /// </summary>
543    public class SDESControl : IControlEncryption
544    {
545        #region private
546        private SDES plugin;
547        private byte[] input;
548        private List<CryptoolStream> listCryptoolStreams = new List<CryptoolStream>();
549        ElectronicCodeBook ecb;
550        CipherBlockChaining cbc;
551        #endregion
552
553        #region events
554        public event KeyPatternChanged keyPatternChanged; //not used, because we only have one key length
555        public event IControlStatusChangedEventHandler OnStatusChanged;
556        #endregion
557
558        #region public
559
560        /// <summary>
561        /// Constructs a new SDESControl
562        /// </summary>
563        /// <param name="Plugin"></param>
564        public SDESControl(SDES Plugin)
565        {
566            this.plugin = Plugin;
567            this.ecb = new ElectronicCodeBook(plugin);
568            this.cbc = new CipherBlockChaining(plugin);
569        }
570
571        /// <summary>
572        /// Called by SDES if its status changes
573        /// </summary>
574        public void onStatusChanged()
575        {
576            if(OnStatusChanged != null)
577                OnStatusChanged(this, true);
578        }
579     
580        /// <summary>
581        /// Called by a Master to start encryption
582        /// </summary>
583        /// <param name="key">key</param>
584        /// <param name="blocksize">blocksize</param>
585        /// <returns>encrypted text</returns>
586        public byte[] Encrypt(byte[] key, int blocksize)
587        {
588            ((SDESSettings)plugin.Settings).Action = 0;
589            return execute(key, blocksize);
590        }
591
592        /// <summary>
593        /// Called by a Master to start decryption
594        /// </summary>
595        /// <param name="key">key</param>
596        /// <param name="blocksize">blocksize</param>
597        /// <returns>decrypted text</returns>
598        public byte[] Decrypt(byte[] key, int blocksize)
599        {
600            ((SDESSettings)plugin.Settings).Action = 1;
601            return execute(key, blocksize);
602        }
603
604        /// <summary>
605        /// Get the key pattern of the SDES algorithm
606        /// </summary>
607        /// <returns>[01][01][01][01][01][01][01][01][01][01]</returns>
608        public string getKeyPattern()
609        {
610            return "[01][01][01][01][01][01][01][01][01][01]";
611        }
612
613        /// <summary>
614        /// Makes a byte Array out of a String
615        /// example
616        /// "10101" -> 1,0,1,0,1
617        ///
618        /// A 0 is interpreted as 0
619        /// any other character as 1
620        /// </summary>
621        /// <param name="key"></param>
622        /// <returns></returns>
623        public byte[] getKeyFromString(string key)
624        {
625            byte[] bkey = new byte[10];
626            int count = 0;
627            foreach (char c in key)
628                if (c == '0')
629                    bkey[count++] = 0;
630                else
631                    bkey[count++] = 1;
632            return bkey;
633        }
634
635        /// <summary>
636        /// Called by the SDES plugin if it is disposing
637        /// closes all privaet streams
638        /// </summary>
639        public void Dispose()
640        {
641            foreach (CryptoolStream cs in listCryptoolStreams)
642                cs.Close();
643        }
644
645        #endregion
646
647        #region private
648
649        /// <summary>
650        /// Called by itself to start encryption/decryption
651        /// </summary>
652        /// <param name="key">key</param>
653        /// <param name="blocksize">blocksize</param>
654        /// <returns>encrypted/decrypted text</returns>
655        private byte[] execute(byte[] key, int blocksize)
656        {
657            byte[] output;
658            if (blocksize > 0)
659                output = new byte[blocksize];
660            else
661                output = new byte[plugin.InputStream.Length];
662
663            if (input == null || plugin.InputChanged)
664            {
665                plugin.InputChanged = false;
666                input = new byte[blocksize];
667
668                byte[] buffer = new byte[1];
669               
670                int i = 0;
671                CryptoolStream inputstream = plugin.InputStream;
672                while ((inputstream.Read(buffer, 0, 1)) > 0 && i < blocksize)
673                {
674                    input[i] = buffer[0];
675                    i++;
676                }
677            }
678         
679            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
680            if (((SDESSettings)plugin.Settings).Mode == 0)
681            {                               
682                output = ecb.decrypt(input, key, blocksize);
683            }
684            else
685            {               
686                output = cbc.decrypt(input, key, Tools.stringToBinaryByteArray(enc.GetString(plugin.InputIV)),blocksize);
687            }           
688           
689            return output;
690        }
691
692        #endregion
693    }
694       
695    /// <summary>
696    /// Encapsulates the SDES algorithm
697    /// </summary>
698    public class SDES_algorithm
699    {
700        private SDES mSdes;         //to call some methods on the plugin
701        private int fkstep = 0;     //for presentation to check the number of fk we are in
702        private int mode = 0;       //for presentation to check the mode we use (0 = en/1 = decrypt)
703
704        public SDES_algorithm(SDES sdes)
705        {
706            this.mSdes = sdes;
707        }
708
709        /// <summary>
710        /// Encrypt-function       
711        /// Encrypts the input plaintext with the given key
712        /// </summary>
713        /// <param name="plaintext">plaintext as byte array of size 8</param>
714        /// <param name="key">key as byte array of size 10</param>
715        /// <returns>ciphertext as byte array of size 8</returns>
716        public byte[] encrypt(byte[] plaintext, byte[] key)
717        {
718            this.mode = 0; // to tell presentation what we are doing
719
720            if (this.mSdes.Presentation.IsVisible)
721            {
722                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
723                {
724                    ((SDESPresentation)mSdes.Presentation).key_txt.Text =
725                    Tools.byteArrayToStringWithSpaces(key);
726                }
727                , null);
728            }
729            //calculate sub key 1
730            byte[] vp10 = p10(key);
731            if (this.mSdes.Presentation.IsVisible)
732            {
733                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
734                {
735                    ((SDESPresentation)mSdes.Presentation).key_txt_p10_input.Text =
736                    Tools.byteArrayToStringWithSpaces(key);
737                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_input_1.Text =
738                    Tools.byteArrayToStringWithSpaces(vp10);
739                }
740                , null);
741            }
742
743            byte[] vls1 = ls_1(vp10);
744            if (this.mSdes.Presentation.IsVisible)
745            {
746                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
747                {
748                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_1_input.Text =
749                    Tools.byteArrayToStringWithSpaces(vls1);
750                }
751                , null);
752            }
753
754            byte[] key1 = p8(vls1);
755            if (this.mSdes.Presentation.IsVisible)
756            {
757                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
758                {
759                    ((SDESPresentation)mSdes.Presentation).key_txt_k1.Text =
760                    Tools.byteArrayToStringWithSpaces(key1);
761                }
762                , null);
763            }
764
765            //calculate sub key 2
766            vls1 = ls_1(vls1);
767            if (this.mSdes.Presentation.IsVisible)
768            {
769                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
770                {
771                    ((SDESPresentation)mSdes.Presentation).key_txt_p10_copy.Text =
772                    Tools.byteArrayToStringWithSpaces(vp10);
773                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_2.Text =
774                    Tools.byteArrayToStringWithSpaces(vp10);
775                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_3.Text =
776                   Tools.byteArrayToStringWithSpaces(vls1);
777                }
778                , null);
779            }
780
781            vls1 = ls_1(vls1);
782            if (this.mSdes.Presentation.IsVisible)
783            {
784                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
785                {
786                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_2_input.Text =
787                    Tools.byteArrayToStringWithSpaces(vls1);
788                }
789               , null);
790            }
791
792            byte[] key2 = p8(vls1);
793            if (this.mSdes.Presentation.IsVisible)
794            {
795                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
796                {
797                    ((SDESPresentation)mSdes.Presentation).key_txt_k2.Text =
798                    Tools.byteArrayToStringWithSpaces(key2);
799                }
800               , null);
801            }
802
803            // ip_inverse(fk_2(sw(fk_1(ip(plaintext))))) :
804
805            byte[] ip = this.ip(plaintext);
806            if (this.mSdes.Presentation.IsVisible)
807            {
808                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
809                {
810                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_plaintext.Text =
811                    Tools.byteArrayToStringWithSpaces(plaintext);
812                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_input.Text =
813                    Tools.byteArrayToStringWithSpaces(plaintext);
814                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_output.Text =
815                    Tools.byteArrayToStringWithSpaces(ip);
816                }
817               , null);
818            }
819
820            byte[] fk1 = fk(ip, key1);
821            if (this.mSdes.Presentation.IsVisible)
822            {
823                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
824                {
825                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_sw_input.Text =
826                    Tools.byteArrayToStringWithSpaces(fk1);                   
827                }
828               , null);
829            }
830
831            byte[] swtch = sw(fk1);
832            if (this.mSdes.Presentation.IsVisible)
833            {
834                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
835                {
836                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_sw_output.Text =
837                    Tools.byteArrayToStringWithSpaces(swtch);
838                }
839               , null);
840            }
841
842            byte[] fk2 = fk(swtch, key2);
843            if (this.mSdes.Presentation.IsVisible)
844            {
845                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
846                {
847                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_invers_input.Text =
848                    Tools.byteArrayToStringWithSpaces(fk2);
849                }
850               , null);
851            }                   
852
853            byte[] ciphertext = ip_inverse(fk2);
854            if (this.mSdes.Presentation.IsVisible)
855            {
856                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
857                {
858                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_invers_output.Text =
859                    Tools.byteArrayToStringWithSpaces(ciphertext);
860                }
861               , null);
862            }   
863
864            return ciphertext;
865
866        }//end encrypt
867
868        /// <summary>
869        /// Decrypt-function
870        /// Decrypts the input ciphertext with the given key
871        /// </summary>
872        /// <param name="ciphertext">ciphertext as byte array of size 8</param>
873        /// <param name="key"> key as byte array of size 10</param>
874        /// <returns>plaintext as byte array of size 8</returns>
875        public byte[] decrypt(byte[] ciphertext, byte[] key)
876        {
877            this.mode = 1; // to tell presentation what we are doing
878
879            if (this.mSdes.Presentation.IsVisible)
880            {
881                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
882                {
883                    ((SDESPresentation)mSdes.Presentation).key_txt.Text =
884                    Tools.byteArrayToStringWithSpaces(key);
885                }
886                , null);
887            }
888            //calculate sub key 1
889            byte[] vp10 = p10(key);
890            if (this.mSdes.Presentation.IsVisible)
891            {
892                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
893                {
894                    ((SDESPresentation)mSdes.Presentation).key_txt_p10_input.Text =
895                    Tools.byteArrayToStringWithSpaces(key);
896                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_input_1.Text =
897                    Tools.byteArrayToStringWithSpaces(vp10);
898                }
899                , null);
900            }
901
902            byte[] vls1 = ls_1(vp10);
903            if (this.mSdes.Presentation.IsVisible)
904            {
905                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
906                {
907                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_1_input.Text =
908                    Tools.byteArrayToStringWithSpaces(vls1);
909                }
910                , null);
911            }
912
913            byte[] key1 = p8(vls1);
914            if (this.mSdes.Presentation.IsVisible)
915            {
916                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
917                {
918                    ((SDESPresentation)mSdes.Presentation).key_txt_k1.Text =
919                    Tools.byteArrayToStringWithSpaces(key1);
920                }
921                , null);
922            }
923
924            //calculate sub key 2
925            vls1 = ls_1(vls1);
926            if (this.mSdes.Presentation.IsVisible)
927            {
928                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
929                {
930                    ((SDESPresentation)mSdes.Presentation).key_txt_p10_copy.Text =
931                    Tools.byteArrayToStringWithSpaces(vp10);
932                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_2.Text =
933                    Tools.byteArrayToStringWithSpaces(vp10);
934                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_3.Text =
935                   Tools.byteArrayToStringWithSpaces(vls1);
936                }
937                , null);
938            }
939
940            vls1 = ls_1(vls1);
941            if (this.mSdes.Presentation.IsVisible)
942            {
943                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
944                {
945                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_2_input.Text =
946                    Tools.byteArrayToStringWithSpaces(vls1);
947                }
948               , null);
949            }
950
951            byte[] key2 = p8(vls1);
952            if (this.mSdes.Presentation.IsVisible)
953            {
954                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
955                {
956                    ((SDESPresentation)mSdes.Presentation).key_txt_k2.Text =
957                    Tools.byteArrayToStringWithSpaces(key2);
958                }
959               , null);
960            }
961
962            // ip_inverse(fk_1(sw(fk_2(ip(ciphertext))))) :
963
964            byte[] ip = this.ip(ciphertext);
965            if (this.mSdes.Presentation.IsVisible)
966            {
967                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
968                {
969                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_plaintext.Text =
970                    Tools.byteArrayToStringWithSpaces(ciphertext);
971                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_input.Text =
972                    Tools.byteArrayToStringWithSpaces(ciphertext);
973                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_output.Text =
974                    Tools.byteArrayToStringWithSpaces(ip);
975                }
976               , null);
977            }
978
979            byte[] fk2 = fk(ip, key2);
980            if (this.mSdes.Presentation.IsVisible)
981            {
982                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
983                {
984                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_sw_input.Text =
985                    Tools.byteArrayToStringWithSpaces(fk2);                 
986                }
987               , null);
988            }
989
990            byte[] swtch = sw(fk2); 
991            if (this.mSdes.Presentation.IsVisible)
992            {
993                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
994                {
995                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_sw_output.Text =
996                    Tools.byteArrayToStringWithSpaces(swtch);
997                }
998               , null);
999            }
1000
1001            byte[] fk1 = fk(swtch, key1);
1002            if (this.mSdes.Presentation.IsVisible)
1003            {
1004                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1005                {
1006                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_invers_input.Text =
1007                    Tools.byteArrayToStringWithSpaces(fk1);
1008                }
1009               , null);
1010            }
1011
1012            byte[] plaintext = ip_inverse(fk1);
1013            if (this.mSdes.Presentation.IsVisible)
1014            {
1015                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1016                {
1017                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_invers_output.Text =
1018                    Tools.byteArrayToStringWithSpaces(plaintext);
1019                }
1020               , null);
1021            }           
1022
1023            return plaintext;
1024
1025        }//end decrypt
1026
1027        ///<summary>
1028        ///p10-function
1029        ///Permutates the input bytes array of "10 bits" to another by
1030        ///the following rule:
1031        ///
1032        ///src    dest
1033        ///1   -> 3
1034        ///2   -> 5
1035        ///3   -> 2
1036        ///4   -> 7
1037        ///5   -> 4
1038        ///6   -> 10
1039        ///7   -> 1
1040        ///8   -> 9
1041        ///9   -> 8
1042        ///10  -> 6
1043        ///</summary>
1044        ///<param name="bits">byte array of size 10</param>
1045        ///<returns>byte array of size 10</returns>
1046        ///
1047        private byte[] p10(byte[] bits)
1048        {
1049
1050            byte[] p10 = new byte[10];
1051
1052            p10[1 - 1] = bits[3 - 1];
1053            p10[2 - 1] = bits[5 - 1];
1054            p10[3 - 1] = bits[2 - 1];
1055            p10[4 - 1] = bits[7 - 1];
1056            p10[5 - 1] = bits[4 - 1];
1057            p10[6 - 1] = bits[10 - 1];
1058            p10[7 - 1] = bits[1 - 1];
1059            p10[8 - 1] = bits[9 - 1];
1060            p10[9 - 1] = bits[8 - 1];
1061            p10[10 - 1] = bits[6 - 1];
1062
1063            //mSdes.GuiLogMessage("P10 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(p10), NotificationLevel.Debug);
1064            return p10;
1065
1066        }//end p10
1067
1068        ///<summary>
1069        ///p8-function
1070        ///Permutates the input bytes array of "8 bits" to another by
1071        ///the following rule:
1072        ///
1073        ///src    dest
1074        ///1   -> 6
1075        ///2   -> 3
1076        ///3   -> 7
1077        ///4   -> 4
1078        ///5   -> 8
1079        ///6   -> 5
1080        ///7   -> 10
1081        ///8   -> 9
1082        ///</summary>
1083        ///<param name="bits">byte array of size 10</param>
1084        ///<returns>byte array of size 8</returns>
1085        private byte[] p8(byte[] bits)
1086        {
1087
1088            byte[] p8 = new byte[8];
1089
1090            p8[1 - 1] = bits[6 - 1];
1091            p8[2 - 1] = bits[3 - 1];
1092            p8[3 - 1] = bits[7 - 1];
1093            p8[4 - 1] = bits[4 - 1];
1094            p8[5 - 1] = bits[8 - 1];
1095            p8[6 - 1] = bits[5 - 1];
1096            p8[7 - 1] = bits[10 - 1];
1097            p8[8 - 1] = bits[9 - 1];
1098
1099            //mSdes.GuiLogMessage("P8 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(p8), NotificationLevel.Debug);
1100            return p8;
1101
1102        }//end p8
1103
1104        ///<summary>
1105        ///ip-function (initial permutation)
1106        ///Permutates the input array of "8 bits" to another by
1107        ///the following rule:
1108        ///
1109        ///src    dest
1110        ///1   -> 2
1111        ///2   -> 6
1112        ///3   -> 3
1113        ///4   -> 1
1114        ///5   -> 4
1115        ///6   -> 8
1116        ///7   -> 5
1117        ///8   -> 7
1118        ///</summary>
1119        ///<param name="bits">byte array of size 8</param>
1120        ///<returns>byte array of size 8</returns>
1121        private byte[] ip(byte[] bits)
1122        {
1123
1124            byte[] ip = new byte[8];
1125
1126            ip[1 - 1] = bits[2 - 1];
1127            ip[2 - 1] = bits[6 - 1];
1128            ip[3 - 1] = bits[3 - 1];
1129            ip[4 - 1] = bits[1 - 1];
1130            ip[5 - 1] = bits[4 - 1];
1131            ip[6 - 1] = bits[8 - 1];
1132            ip[7 - 1] = bits[5 - 1];
1133            ip[8 - 1] = bits[7 - 1];
1134
1135            //mSdes.GuiLogMessage("ip with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ip), NotificationLevel.Debug);
1136            return ip;
1137
1138        }//end ip
1139
1140        ///<summary>
1141        ///ip^-1-function (initial permutation inverse)
1142        ///Permutates the input array of "8 bits" to another by
1143        ///the following rule:
1144        ///
1145        ///src    dest
1146        ///1   -> 4
1147        ///2   -> 1
1148        ///3   -> 3
1149        ///4   -> 5
1150        ///5   -> 7
1151        ///6   -> 2
1152        ///7   -> 8
1153        ///8   -> 6
1154        ///</summary>
1155        ///<param name="bits">byte array of size 8</param>
1156        ///<returns>byte array of size 8</returns>
1157        private byte[] ip_inverse(byte[] bits)
1158        {
1159
1160            byte[] ip_inverse = new byte[8];
1161
1162            ip_inverse[1 - 1] = bits[4 - 1];
1163            ip_inverse[2 - 1] = bits[1 - 1];
1164            ip_inverse[3 - 1] = bits[3 - 1];
1165            ip_inverse[4 - 1] = bits[5 - 1];
1166            ip_inverse[5 - 1] = bits[7 - 1];
1167            ip_inverse[6 - 1] = bits[2 - 1];
1168            ip_inverse[7 - 1] = bits[8 - 1];
1169            ip_inverse[8 - 1] = bits[6 - 1];
1170
1171            //mSdes.GuiLogMessage("ip_inverse with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ip_inverse), NotificationLevel.Debug);             
1172            return ip_inverse;
1173
1174        }//end ip_inverse
1175
1176        ///<summary>
1177        ///fk-function
1178        ///
1179        ///combines the following functions:
1180        ///
1181        ///right is the right part of the input array
1182        ///left is the left part of the input array
1183        ///
1184        ///(right | left) := (inputarray))
1185        ///ret := exclusive_or(left,F(right,key)) + right)
1186        ///</summary>
1187        ///<param name="bits">byte array of size 8</param>
1188        ///<param name="key">byte array of size 8</param>
1189        ///<returns>byte array of size 8</returns>
1190        private byte[] fk(byte[] bits, byte[] key)
1191        {
1192            byte[] left = { bits[1 - 1], bits[2 - 1], bits[3 - 1], bits[4 - 1] };
1193            byte[] right = { bits[5 - 1], bits[6 - 1], bits[7 - 1], bits[8 - 1] };
1194
1195            byte[] exclusive_oder = Tools.exclusive_or(left, F(right, key));
1196
1197            byte[] ret = {exclusive_oder[1-1],exclusive_oder[2-1],exclusive_oder[3-1],exclusive_oder[4-1],
1198                                     right[1-1],right[2-1],right[3-1],right[4-1]};
1199
1200            fkstep++;
1201            if (fkstep == 2)
1202                fkstep = 0;
1203
1204            //mSdes.GuiLogMessage("fk with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);
1205            return ret;
1206
1207        }//end fk
1208
1209        ///<summary>
1210        ///ls-1 function
1211        ///</summary>
1212        ///<param name="bits">byte array of size 10</param>
1213        ///<returns>byte array of size 10</returns>
1214        private byte[] ls_1(byte[] bits)
1215        {
1216
1217            byte[] ls_1 = new byte[10];
1218
1219            ls_1[1 - 1] = bits[2 - 1];
1220            ls_1[2 - 1] = bits[3 - 1];
1221            ls_1[3 - 1] = bits[4 - 1];
1222            ls_1[4 - 1] = bits[5 - 1];
1223            ls_1[5 - 1] = bits[1 - 1];
1224            ls_1[6 - 1] = bits[7 - 1];
1225            ls_1[7 - 1] = bits[8 - 1];
1226            ls_1[8 - 1] = bits[9 - 1];
1227            ls_1[9 - 1] = bits[10 - 1];
1228            ls_1[10 - 1] = bits[6 - 1];
1229
1230            //mSdes.GuiLogMessage("ls-1 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ls_1), NotificationLevel.Debug);
1231            return ls_1;
1232
1233        }//end ls_1
1234
1235        ///<summary>
1236        ///switch-function
1237        ///
1238        ///switches the left side and the right side of the 8 bit array
1239        ///(left|right) -> (right|left)
1240        ///</summary>
1241        ///<param name="bits">byte array of size 8</param>
1242        ///<returns>byte array of size 8</returns>
1243        private byte[] sw(byte[] bits)
1244        {
1245
1246            byte[] ret = {bits[5-1],bits[6-1],bits[7-1],bits[8-1],
1247                                         bits[1-1],bits[2-1],bits[3-1],bits[4-1]};
1248
1249            //mSdes.GuiLogMessage("sw with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);
1250            return ret;
1251
1252        }//end sw
1253
1254        ///<summary>
1255        ///F-function
1256        ///
1257        ///combines both s-boxes and permutates the return value with p4
1258        ///p4( s0(exclusive_or(ep(number),key) | s1(exclusive_or(ep(number),key) )
1259        ///</summary>
1260        ///<param name="bits">byte array of size 8</param>
1261        ///<param name="bits">key of size 8</param>
1262        ///<returns>byte array of size 8</returns>
1263        private byte[] F(byte[] bits, byte[] key)
1264        {
1265
1266            byte[] ep = this.ep(bits);
1267
1268            byte[] exclusive = Tools.exclusive_or(ep, key);
1269
1270            byte[] s0_input = { exclusive[1 - 1], exclusive[2 - 1], exclusive[3 - 1], exclusive[4 - 1] };
1271            byte[] s0 = sbox_0(s0_input);
1272
1273            byte[] s1_input = { exclusive[5 - 1], exclusive[6 - 1], exclusive[7 - 1], exclusive[8 - 1] };
1274            byte[] s1 = sbox_1(s1_input);
1275
1276            byte[] s0_s1 = { s0[1 - 1], s0[2 - 1], s1[1 - 1], s1[2 - 1] };
1277            byte[] ret = p4(s0_s1);
1278
1279            if (this.mSdes.Presentation.IsVisible)
1280            {
1281                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1282                {
1283                    if (mode == 0 && fkstep == 0)
1284                    {
1285                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_sbox1_output.Text =
1286                        Tools.byteArrayToStringWithSpaces(ret);
1287                    }
1288                    if (mode == 0 && fkstep == 1)
1289                    {
1290                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_sbox2_output.Text =
1291                        Tools.byteArrayToStringWithSpaces(ret);
1292                    }
1293                    if (mode == 1 && fkstep == 0)
1294                    {
1295                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_sbox1_output.Text =
1296                        Tools.byteArrayToStringWithSpaces(ret);
1297                    }
1298                    if (mode == 1 && fkstep == 1)
1299                    {
1300                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_sbox2_output.Text =
1301                        Tools.byteArrayToStringWithSpaces(ret);
1302                    }
1303                }
1304               , null);
1305            }
1306
1307            //mSdes.GuiLogMessage("F with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(key) + " ist " + Tools.intArray2String(ret), NotificationLevel.Debug);
1308            return ret;
1309
1310        }//end F
1311
1312        ///<summary>
1313        ///p4-function
1314        ///Permutates the input array of "4 bits" to another by
1315        ///the following rule:
1316        ///
1317        ///src    dest
1318        ///1   -> 2
1319        ///2   -> 4
1320        ///3   -> 3
1321        ///4   -> 1
1322        ///</summary>
1323        ///<param name="bits">byte array of size 4</param>
1324        ///<returns>byte array of size 4</returns>
1325        private byte[] p4(byte[] bits)
1326        {
1327
1328            byte[] ret = new byte[4];
1329            ret[1 - 1] = bits[2 - 1];
1330            ret[2 - 1] = bits[4 - 1];
1331            ret[3 - 1] = bits[3 - 1];
1332            ret[4 - 1] = bits[1 - 1];
1333
1334            return ret;
1335
1336        }//end p4
1337
1338        ///<summary>
1339        ///ep-function
1340        ///Permutates the input array of "4 bits" to another array of "8 bits" by
1341        ///the following rule:
1342        ///
1343        ///src    dest
1344        ///1   -> 4
1345        ///2   -> 1
1346        ///3   -> 2
1347        ///4   -> 3
1348        ///5   -> 2
1349        ///6   -> 3
1350        ///7   -> 4
1351        ///8   -> 1
1352        ///</summary>
1353         ///<param name="bits">byte array of size 4</param>
1354        ///<returns>byte array of size 8</returns>
1355        private byte[] ep(byte[] bits)
1356        {
1357
1358            byte[] ep = new byte[8];
1359            ep[1 - 1] = bits[4 - 1];
1360            ep[2 - 1] = bits[1 - 1];
1361            ep[3 - 1] = bits[2 - 1];
1362            ep[4 - 1] = bits[3 - 1];
1363            ep[5 - 1] = bits[2 - 1];
1364            ep[6 - 1] = bits[3 - 1];
1365            ep[7 - 1] = bits[4 - 1];
1366            ep[8 - 1] = bits[1 - 1];
1367
1368            if (this.mSdes.Presentation.IsVisible)
1369            {
1370                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1371                {
1372                    if (mode == 0 && fkstep == 0)
1373                    {
1374                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_ep_output.Text =
1375                        Tools.byteArrayToStringWithSpaces(ep);
1376                    }
1377                    if (mode == 0 && fkstep == 1)
1378                    {
1379                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_ep_output1.Text =
1380                        Tools.byteArrayToStringWithSpaces(ep);
1381                    }
1382                    if (mode == 1 && fkstep == 0)
1383                    {
1384                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_ep_output.Text =
1385                        Tools.byteArrayToStringWithSpaces(ep);
1386                    }
1387                    if (mode == 1 && fkstep == 1)
1388                    {
1389                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_ep_output1.Text =
1390                        Tools.byteArrayToStringWithSpaces(ep);
1391                    }
1392                }
1393               , null);
1394            }
1395
1396            return ep;
1397        }
1398
1399        ///<summary>
1400        ///SBox-0
1401        ///
1402        ///S0 =  1 0 3 2
1403        ///      3 2 1 0
1404        ///      0 2 1 3   
1405        ///      3 1 3 2           
1406        ///</summary>
1407        ///<param name="bits">byte array of size 4</param>
1408        ///<returns>byte array of size 2</returns>
1409        private byte[] sbox_0(byte[] bits)
1410        {
1411
1412            int row = 2 * bits[1 - 1] + 1 * bits[4 - 1];
1413            int column = 2 * bits[2 - 1] + 1 * bits[3 - 1];
1414
1415            byte[,][] sbox_0 = new byte[4, 4][]
1416                            {
1417                            {new byte[] {0,1}, new byte[] {0,0}, new byte[] {1,1}, new byte[] {1,0}},
1418                                                {new byte[] {1,1}, new byte[] {1,0}, new byte[] {0,1}, new byte[] {0,0}},
1419                                                {new byte[] {0,0}, new byte[] {1,0}, new byte[] {0,1}, new byte[] {1,1}},
1420                                                {new byte[] {1,1}, new byte[] {0,1}, new byte[] {1,1}, new byte[] {1,0}}
1421                            };
1422
1423            byte[] ret = sbox_0[row, column];
1424
1425            if (this.mSdes.Presentation.IsVisible)
1426            {
1427                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1428                {
1429                    if (mode == 0 && fkstep == 0)
1430                    {
1431                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s0_1_output.Text =
1432                        Tools.byteArrayToStringWithSpaces(ret);
1433                    }
1434                    if (mode == 0 && fkstep == 1)
1435                    {
1436                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s0_2_output.Text =
1437                        Tools.byteArrayToStringWithSpaces(ret);
1438                    }
1439                    if (mode == 1 && fkstep == 0)
1440                    {
1441                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s0_1_output.Text =
1442                        Tools.byteArrayToStringWithSpaces(ret);
1443                    }
1444                    if (mode == 1 && fkstep == 1)
1445                    {
1446                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s0_2_output.Text =
1447                        Tools.byteArrayToStringWithSpaces(ret);
1448                    }
1449                }
1450               , null);
1451            }
1452
1453            //mSdes.GuiLogMessage("S0 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);
1454            return ret;
1455
1456        }//end sbox-0
1457
1458
1459        ///<summary>
1460        ///SBox-1
1461        ///
1462        ///S1 =  0 1 2 3
1463        ///      2 0 1 3
1464        ///      3 0 1 0
1465        ///      2 1 0 3
1466        ///</summary>
1467        ///<param name="bits">byte array of size 4</param>
1468        ///<returns>byte array of size 2</returns>
1469        private byte[] sbox_1(byte[] bits)
1470        {
1471
1472            int row = 2 * bits[1 - 1] + 1 * bits[4 - 1];
1473            int column = 2 * bits[2 - 1] + 1 * bits[3 - 1];
1474
1475            byte[,][] sbox_1 = new byte[4, 4][]
1476                            {
1477                            {new byte[] {0,0}, new byte[] {0,1}, new byte[] {1,0}, new byte[] {1,1}},
1478                                                        {new byte[] {1,0}, new byte[] {0,0}, new byte[] {0,1}, new byte[] {1,1}},
1479                                                        {new byte[] {1,1}, new byte[] {0,0}, new byte[] {0,1}, new byte[] {0,0}},
1480                                                        {new byte[] {1,0}, new byte[] {0,1}, new byte[] {0,0}, new byte[] {1,1}}
1481                            };
1482
1483            byte[] ret = sbox_1[row, column];
1484
1485            if (this.mSdes.Presentation.IsVisible)
1486            {
1487                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1488                {
1489                    if (mode == 0 && fkstep == 0)
1490                    {
1491                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s1_1_output.Text =
1492                        Tools.byteArrayToStringWithSpaces(ret);
1493                    }
1494                    if (mode == 0 && fkstep == 1)
1495                    {
1496                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s1_2_output.Text =
1497                        Tools.byteArrayToStringWithSpaces(ret);
1498                    }
1499                    if (mode == 1 && fkstep == 0)
1500                    {
1501                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s1_1_output.Text =
1502                        Tools.byteArrayToStringWithSpaces(ret);
1503                    }
1504                    if (mode == 1 && fkstep == 1)
1505                    {
1506                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s1_2_output.Text =
1507                        Tools.byteArrayToStringWithSpaces(ret);
1508                    }
1509                }
1510               , null);
1511            }
1512
1513            //mSdes.GuiLogMessage("S1 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);             
1514            return ret;
1515
1516        }//end sbox-1
1517
1518    }
1519
1520    ///<summary>
1521    ///Encapsulates some necessary functions
1522    ///</summary>
1523    public class Tools
1524    {
1525
1526        /// <summary>
1527        /// transforms a byte array into a String with spaces after each byte
1528        /// example:
1529        ///     1,0 => "1 0"
1530        /// </summary>
1531        /// <param name="byt">byt</param>
1532        /// <returns>s</returns>
1533        public static String byteArrayToStringWithSpaces(byte[] byt)
1534        {
1535            String s = "";
1536
1537            foreach (byte b in byt)
1538            {
1539                s = s + b + " ";
1540            }
1541            return s;
1542        }
1543        ///<summary>
1544        ///Converts an byte array to a String
1545        ///</summary>
1546        ///<param name="bits">byte array of size n</param>
1547        ///<returns>String</returns>
1548        public static String byteArray2String(byte[] bits)
1549        {
1550
1551            String ret = "";
1552            for (int i = 0; i < bits.Length; i++)
1553            {
1554                ret += ("" + bits[i]);
1555            }
1556            return ret;
1557
1558        }//end byteArray2String
1559
1560        ///<summary>
1561        ///Converts the given byte array to a printable String
1562        ///
1563        ///example {72, 101, 108, 108, 111} -> "Hello"
1564        ///</summary>
1565        ///<param name="bits">byte array of size n</param>
1566        ///<returns>String</returns>
1567        public static String byteArray2PrintableString(byte[] bits)
1568        {
1569
1570            String ret = "";
1571            for (int i = 0; i < bits.Length; i++)
1572            {
1573                ret += ("" + (char)bits[i]);
1574            }
1575            return ret;
1576
1577        }// byteArray2PrintableString
1578
1579        ///<summary>
1580        ///equals-function
1581        ///
1582        ///returns true if both integer arrays are equal
1583        ///</summary>
1584        ///<param name="a">byte array of size n</param>
1585        ///<param name="b">byte array of size n</param>
1586        ///<returns>bool</returns>
1587        public static bool byteArrays_Equals(byte[] a, byte[] b)
1588        {
1589
1590            for (int i = 0; i < a.Length; i++)
1591            {
1592                if (a[i] != b[i])
1593                {
1594                    return false;
1595                }
1596            }
1597
1598            return true;
1599
1600        }//end byteArrays_Equals       
1601
1602        ///<summary>
1603        ///converts an Byte to an byte array of (0,1)
1604        ///
1605        ///100 -> {1,1,0,0,1,0,0}
1606        ///</summary>
1607        ///<param name="byt">byte array of size n</param>
1608        ///<returns>byte array</returns>
1609        public static byte[] byteToByteArray(byte byt)
1610        {
1611
1612            byte[] bytearray = new byte[8];
1613
1614            for (int i = 7; i >= 0; i--)
1615            {
1616
1617                bytearray[i] = (byte)(byt % 2);
1618                byt = (byte)Math.Floor((double)(byt / 2));
1619
1620            }
1621
1622            return bytearray;
1623
1624        }//end byteTointArray
1625
1626        ///<summary>
1627        ///converts an byte array of (0,1) to an byte
1628        ///
1629        ///{1,1,0,0,1,0,0} -> 100
1630        ///</summary>
1631        ///<param name="bytearray">byte array of size n</param>
1632        ///<returns>byte</returns>
1633        public static byte byteArrayToByte(byte[] bytearray)
1634        {
1635
1636            int byt = 0;
1637
1638            byt = (bytearray[0] * 128)
1639                        + (bytearray[1] * 64)
1640                        + (bytearray[2] * 32)
1641                        + (bytearray[3] * 16)
1642                        + (bytearray[4] * 8)
1643                        + (bytearray[5] * 4)
1644                        + (bytearray[6] * 2)
1645                        + (bytearray[7] * 1);
1646
1647            return (byte)byt;
1648
1649        }//end byteArrayToInteger
1650
1651        ///<summary>
1652        ///Exclusiv-OR function
1653        ///
1654        ///Does a exlusiv-or on two byte arrays
1655        ///
1656        ///example {1,0,1} XOR {1,0,0} -> {0,0,1}
1657        ///</summary>
1658        ///<param name="bitsA">byte array of size n</param>
1659        ///<param name="bitsB">byte array of size n</param>
1660        ///<returns>byte array of size n</returns>
1661        public static byte[] exclusive_or(byte[] bitsA, byte[] bitsB)
1662        {
1663
1664            byte[] exclusive_or_AB = new byte[bitsA.Length];
1665
1666            for (int i = 0; i < bitsA.Length; i++)
1667            {
1668
1669                if ((bitsA[i] == 0 && bitsB[i] == 1) ||
1670                   (bitsA[i] == 1 && bitsB[i] == 0)
1671                )
1672                {
1673                    exclusive_or_AB[i] = 1;
1674                }
1675                else
1676                {
1677                    exclusive_or_AB[i] = 0;
1678                }//end if
1679
1680            }//end for
1681
1682            return exclusive_or_AB;
1683
1684        }//end exclusive_or
1685
1686        ///<summary>
1687        ///converts string to an byte array
1688        ///
1689        ///example "Hello" -> {72, 101, 108, 108, 111}
1690        ///</summary>
1691        ///<param name="s">String</param>
1692        ///<returns>byte array</returns>
1693        public static byte[] stringToByteArray(String s)
1694        {
1695            byte[] bytearray = new byte[s.Length];
1696
1697            for (int i = 0; i < s.Length; i++)
1698            {
1699                bytearray[i] = (byte)s[i];
1700            }
1701
1702            return bytearray;
1703
1704        }// end stringToByteArray
1705
1706        ///<summary>
1707        ///converts a binary string to an byte array
1708        ///
1709        ///example "10010" -> {1, 0, 0, 1, 0}
1710        ///</summary>
1711        ///<param name="s">String</param>
1712        ///<returns>byte array</returns>
1713        public static byte[] stringToBinaryByteArray(String s)
1714        {
1715            byte[] bytearray = new byte[s.Length];
1716
1717            for (int i = 0; i < s.Length; i++)
1718            {
1719                if (s[i] == '1')
1720                {
1721                    bytearray[i] = 1;
1722                }
1723                else if (s[i] == '0')
1724                {
1725                    bytearray[i] = 0;
1726                }
1727                else
1728                {
1729                    throw new Exception("Invalid Character '" + s[i] + "' at position " + i + " in String which represents binary values: " + s);
1730                }
1731            }
1732
1733            return bytearray;
1734
1735        }// end stringToByteArray
1736    }
1737
1738    ///<summary>
1739    ///Encapsulates the CipherBlockChaining algorithm
1740    ///</summary>
1741    public class CipherBlockChaining
1742    {
1743
1744        private SDES mSdes;
1745        private SDES_algorithm mAlgorithm;
1746
1747        /// <summary>
1748        /// Constructs a CipherBlockChaining for SDES
1749        /// </summary>
1750        /// <param name="sdes">plugin</param>
1751        public CipherBlockChaining(SDES sdes)
1752        {
1753            this.mSdes = sdes;
1754            this.mAlgorithm = new SDES_algorithm(sdes);
1755        }
1756
1757        ///<summary>
1758        ///Encrypts the given plaintext with the given key
1759        ///using CipherBlockChaining
1760        ///</summary>
1761        public void encrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key, byte[] vector)
1762        {
1763
1764            byte[] buffer = new byte[1];
1765            int position = 0;
1766
1767            while ((inputstream.Read(buffer, 0, 1)) > 0 && !this.mSdes.getStop())
1768            {
1769                //Step 1 get plaintext symbol
1770                byte symbol = buffer[0];
1771                //Step 2 exclusiv OR with vector
1772                vector = Tools.exclusive_or(vector, Tools.byteToByteArray(symbol));
1773                //Step 3 decrypt vector with key
1774                vector = mAlgorithm.encrypt(vector, key);
1775                //Step 4 store symbol in ciphertext
1776                outputstream.Write(Tools.byteArrayToByte(vector));
1777
1778                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1779                {
1780                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1781                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1782                }
1783                outputstream.Flush();
1784            }
1785
1786        }//end encrypt
1787
1788        ///
1789        ///Encrypts the given plaintext with the given key
1790        ///using CipherBlockChaining
1791        ///
1792        /// blocksize tells the algorithm how many bytes it has to encrypt
1793        /// blocksize = 0 => encrypt all
1794        public byte[] encrypt(byte[] input, byte[] key, byte[] vector, [Optional, DefaultParameterValue(0)] int blocksize)
1795        {
1796            int until = input.Length;           
1797
1798            if (blocksize < until && blocksize > 0)
1799                until = blocksize;
1800
1801            byte[] output = new byte[until];
1802
1803            for (int i = 0; i < until; i++)
1804            {
1805                vector = Tools.exclusive_or(vector, Tools.byteToByteArray(input[i]));
1806                vector = mAlgorithm.encrypt(vector, key);
1807                output[i] = Tools.byteArrayToByte(vector);
1808
1809            }//end while
1810           
1811            return output;
1812
1813        }//end encrypt
1814
1815        ///<summary>
1816        ///Decrypts the given plaintext with the given Key
1817        ///using CipherBlockChaining
1818        ///</summary>
1819        public void decrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key, byte[] vector)
1820        {
1821
1822            byte[] buffer = new byte[1];
1823            int position = 0;
1824
1825            while ((inputstream.Read(buffer, 0, 1)) > 0 && !this.mSdes.getStop())
1826            {
1827                //Step 1 get Symbol of Ciphertext
1828                byte symbol = buffer[0];
1829                //Step 2 Decrypt symbol with key and exclusiv-or with vector
1830                outputstream.Write((Tools.byteArrayToByte(Tools.exclusive_or(mAlgorithm.decrypt(Tools.byteToByteArray(symbol), key), vector))));
1831                //Step 3 let vector be the decrypted Symbol
1832                vector = Tools.byteToByteArray(buffer[0]);
1833
1834                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1835                {
1836                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1837                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1838                }
1839                outputstream.Flush();
1840            }
1841
1842        }//end decrypt
1843
1844        ///
1845        ///Decrypt the given plaintext with the given key
1846        ///using CipherBlockChaining
1847        ///
1848        /// blocksize tells the algorithm how many bytes it has to encrypt
1849        /// blocksize = 0 => encrypt all
1850        public byte[] decrypt(byte[] input, byte[] key, byte[] vector, [Optional, DefaultParameterValue(0)] int blocksize)
1851        {
1852
1853            int until = input.Length;
1854           
1855            if (blocksize < until && blocksize > 0)
1856                until = blocksize;
1857
1858            byte[] output = new byte[until];
1859
1860            for (int i = 0; i < until; i++)
1861            {
1862                output[i] = (Tools.byteArrayToByte(Tools.exclusive_or(mAlgorithm.decrypt(Tools.byteToByteArray(input[i]), key), vector)));
1863                vector = Tools.byteToByteArray(input[i]);
1864                           
1865            }//end while
1866
1867            return output;
1868
1869        }//end encrypt
1870
1871    }//end class CipherBlockChaining
1872
1873    ///<summary>
1874    ///Encapsulates the ElectronicCodeBook algorithm
1875    ///</summary>
1876    public class ElectronicCodeBook
1877    {
1878
1879        private SDES mSdes;
1880        private SDES_algorithm mAlgorithm;
1881
1882        /// <summary>
1883        /// Constructs a ElectronicCodeBook for SDES
1884        /// </summary>
1885        /// <param name="sdes">plugin</param>
1886        public ElectronicCodeBook(SDES sdes)
1887        {
1888            this.mSdes = sdes;
1889            this.mAlgorithm = new SDES_algorithm(sdes);
1890        }
1891
1892        ///
1893        ///Encrypts the given plaintext with the given key
1894        ///using ElectronicCodeBookMode
1895        ///
1896        public void encrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key)
1897        {
1898
1899            byte[] buffer = new byte[1];
1900            int position = 0;
1901
1902            while ((inputstream.Read(buffer, 0, 1)) > 0 && !this.mSdes.getStop())
1903            {
1904                //Step 1 get plaintext symbol
1905                byte symbol = buffer[0]; ;
1906                //Step 2 encrypt symbol
1907                outputstream.Write(Tools.byteArrayToByte(this.mAlgorithm.encrypt(Tools.byteToByteArray(symbol), key)));
1908
1909                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1910                {
1911                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1912                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1913                }
1914                outputstream.Flush();
1915
1916            }//end while
1917
1918        }//end encrypt
1919
1920        ///
1921        ///Encrypts the given plaintext with the given key
1922        ///using ElectronicCodeBookMode
1923        ///
1924        /// blocksize tells the algorithm how many bytes it has to encrypt
1925        /// blocksize = 0 => encrypt all
1926        public byte[] encrypt(byte[] input, byte[] key, [Optional, DefaultParameterValue(0)] int blocksize)
1927        {
1928
1929            int until = input.Length;
1930
1931            if(blocksize < until && blocksize > 0)
1932                until = blocksize;
1933
1934            byte[] output = new byte[until];
1935
1936            for(int i=0;i<until;i++)
1937            {               
1938                //Step 2 encrypt symbol
1939                output[i] = Tools.byteArrayToByte(this.mAlgorithm.encrypt(Tools.byteToByteArray(input[i]), key));
1940
1941            }//end while
1942
1943            return output;
1944
1945        }//end encrypt
1946
1947        ///<summary>
1948        ///Decrypts the given plaintext with the given Key
1949        ///using ElectronicCodeBook mode
1950        ///</summary>
1951        public void decrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key)
1952        {
1953
1954            byte[] buffer = new byte[1];
1955            int position = 0;
1956
1957            while ((inputstream.Read(buffer, 0, 1)) > 0 && !this.mSdes.getStop())
1958            {
1959                //Step 1 get plaintext symbol
1960                byte symbol = buffer[0];
1961                //Step 2 encrypt symbol
1962                outputstream.Write(Tools.byteArrayToByte(this.mAlgorithm.decrypt(Tools.byteToByteArray(symbol), key)));
1963
1964                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1965                {
1966                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1967                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1968                }
1969                outputstream.Flush();
1970
1971            }//end while
1972
1973        }//end decrypt
1974
1975        ///
1976        ///Decrypt the given plaintext with the given key
1977        ///using ElectronicCodeBookMode
1978        ///
1979        /// blocksize tells the algorithm how many bytes it has to decrypt
1980        /// blocksize = 0 => encrypt all
1981        public byte[] decrypt(byte[] input, byte[] key, [Optional, DefaultParameterValue(0)] int blocksize)
1982        {
1983            int until = input.Length;
1984
1985            if (blocksize < until && blocksize > 0)
1986                until = blocksize;
1987           
1988            byte[] output = new byte[until];
1989
1990            for (int i = 0; i < until; i++)
1991            {
1992                //Step 2 encrypt symbol
1993                output[i] = Tools.byteArrayToByte(this.mAlgorithm.decrypt(Tools.byteToByteArray(input[i]), key));
1994
1995            }//end while
1996
1997            return output;
1998
1999        }//end encrypt
2000
2001    }//end class ElectronicCodeBook
2002
2003}//end namespace Cryptool.Plugins.Cryptography.Encryption
Note: See TracBrowser for help on using the repository browser.