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

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

renamed "blocksize" to "bytesToUse"

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