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

Last change on this file since 1121 was 1121, checked in by kohnen, 12 years ago
  • deleted setInput-function from IControlEncryption and all Plugins using IControlEncryption
  • some changes at TranspositionAnalyser plugin & Settings
  • new TranspositionAnalyser sample
File size: 71.7 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        public byte[] Decrypt(byte[] ciphertext, byte[] key)
589        {
590            throw new NotImplementedException();
591        }
592
593        /// <summary>
594        /// Called by a Master to start decryption
595        /// </summary>
596        /// <param name="key">key</param>
597        /// <param name="bytesToUse">bytesToUse</param>
598        /// <returns>decrypted text</returns>
599        public byte[] Decrypt(byte[] key, int bytesToUse)
600        {
601            return execute(key, bytesToUse, 1);
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, ref int[] arrayPointers, ref int[] arraySuccessors, ref int[] arrayUppers)
624        {
625            byte[] bkey = new byte[10];
626            int count = 0;
627            foreach (char c in key)
628                if (c == '*')
629                    return null;    //blocks not supported yet
630                else if (c == '0')
631                    bkey[count++] = 0;
632                else
633                    bkey[count++] = 1;
634            return bkey;
635        }
636
637        public IControlEncryption clone()
638        {
639            return new SDESControl(plugin);
640        }
641
642        public void Dispose()
643        {
644            //closeStreams();
645        }
646
647        #endregion
648
649        #region private
650
651        /// <summary>
652        /// Called by itself to start encryption/decryption
653        /// </summary>
654        /// <param name="key">key</param>
655        /// <param name="bytesToUse">bytesToUse</param>
656        /// <returns>encrypted/decrypted text</returns>
657        private byte[] execute(byte[] key, int bytesToUse, int action)
658        {
659            byte[] output;
660            if (bytesToUse > 0)
661                output = new byte[bytesToUse];
662            else
663                output = new byte[plugin.InputStream.Length];
664
665            if (input == null || plugin.InputChanged)
666            {
667                plugin.InputChanged = false;
668                input = new byte[bytesToUse];
669
670                byte[] buffer = new byte[1];
671               
672                int i = 0;
673                CryptoolStream inputstream = plugin.InputStream;
674                while ((inputstream.Read(buffer, 0, 1)) > 0 && i < bytesToUse)
675                {
676                    input[i] = buffer[0];
677                    i++;
678                }
679            }
680         
681            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
682            if (((SDESSettings)plugin.Settings).Mode == 0 && action == 0)
683            {                               
684                output = ecb.encrypt(input, key, bytesToUse);
685            }
686            else if(((SDESSettings)plugin.Settings).Mode == 1 && action == 0)
687            {               
688                output = cbc.encrypt(input, key, Tools.stringToBinaryByteArray(enc.GetString(plugin.InputIV)),bytesToUse);
689            }           
690            else if(((SDESSettings)plugin.Settings).Mode == 0 && action == 1)
691            {
692                output = ecb.decrypt(input, key,bytesToUse);
693            }
694            else if (((SDESSettings)plugin.Settings).Mode == 1 && action == 1)
695            {
696                output = cbc.decrypt(input, key, Tools.stringToBinaryByteArray(enc.GetString(plugin.InputIV)), bytesToUse);
697            }   
698            return output;
699        }
700
701        #endregion
702
703        #region IControlEncryption Member
704
705
706        public void changeSettings(string setting, object value)
707        {
708
709        }
710        #endregion
711    }
712       
713    /// <summary>
714    /// Encapsulates the SDES algorithm
715    /// </summary>
716    public class SDES_algorithm
717    {
718        private SDES mSdes;         //to call some methods on the plugin
719        private int fkstep = 0;     //for presentation to check the number of fk we are in
720        private int mode = 0;       //for presentation to check the mode we use (0 = en/1 = decrypt)
721
722        public SDES_algorithm(SDES sdes)
723        {
724            this.mSdes = sdes;
725        }
726
727        /// <summary>
728        /// Encrypt-function       
729        /// Encrypts the input plaintext with the given key
730        /// </summary>
731        /// <param name="plaintext">plaintext as byte array of size 8</param>
732        /// <param name="key">key as byte array of size 10</param>
733        /// <returns>ciphertext as byte array of size 8</returns>
734        public byte[] encrypt(byte[] plaintext, byte[] key)
735        {
736            this.mode = 0; // to tell presentation what we are doing
737
738            if (this.mSdes.Presentation.IsVisible)
739            {
740                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
741                {
742                    ((SDESPresentation)mSdes.Presentation).key_txt.Text =
743                    Tools.byteArrayToStringWithSpaces(key);
744                }
745                , null);
746            }
747            //calculate sub key 1
748            byte[] vp10 = p10(key);
749            if (this.mSdes.Presentation.IsVisible)
750            {
751                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
752                {
753                    ((SDESPresentation)mSdes.Presentation).key_txt_p10_input.Text =
754                    Tools.byteArrayToStringWithSpaces(key);
755                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_input_1.Text =
756                    Tools.byteArrayToStringWithSpaces(vp10);
757                }
758                , null);
759            }
760
761            byte[] vls1 = ls_1(vp10);
762            if (this.mSdes.Presentation.IsVisible)
763            {
764                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
765                {
766                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_1_input.Text =
767                    Tools.byteArrayToStringWithSpaces(vls1);
768                }
769                , null);
770            }
771
772            byte[] key1 = p8(vls1);
773            if (this.mSdes.Presentation.IsVisible)
774            {
775                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
776                {
777                    ((SDESPresentation)mSdes.Presentation).key_txt_k1.Text =
778                    Tools.byteArrayToStringWithSpaces(key1);
779                }
780                , null);
781            }
782
783            //calculate sub key 2
784            vls1 = ls_1(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_p10_copy.Text =
790                    Tools.byteArrayToStringWithSpaces(vp10);
791                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_2.Text =
792                    Tools.byteArrayToStringWithSpaces(vp10);
793                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_3.Text =
794                   Tools.byteArrayToStringWithSpaces(vls1);
795                }
796                , null);
797            }
798
799            vls1 = ls_1(vls1);
800            if (this.mSdes.Presentation.IsVisible)
801            {
802                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
803                {
804                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_2_input.Text =
805                    Tools.byteArrayToStringWithSpaces(vls1);
806                }
807               , null);
808            }
809
810            byte[] key2 = p8(vls1);
811            if (this.mSdes.Presentation.IsVisible)
812            {
813                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
814                {
815                    ((SDESPresentation)mSdes.Presentation).key_txt_k2.Text =
816                    Tools.byteArrayToStringWithSpaces(key2);
817                }
818               , null);
819            }
820
821            // ip_inverse(fk_2(sw(fk_1(ip(plaintext))))) :
822
823            byte[] ip = this.ip(plaintext);
824            if (this.mSdes.Presentation.IsVisible)
825            {
826                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
827                {
828                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_plaintext.Text =
829                    Tools.byteArrayToStringWithSpaces(plaintext);
830                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_input.Text =
831                    Tools.byteArrayToStringWithSpaces(plaintext);
832                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_output.Text =
833                    Tools.byteArrayToStringWithSpaces(ip);
834                }
835               , null);
836            }
837
838            byte[] fk1 = fk(ip, key1);
839            if (this.mSdes.Presentation.IsVisible)
840            {
841                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
842                {
843                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_sw_input.Text =
844                    Tools.byteArrayToStringWithSpaces(fk1);                   
845                }
846               , null);
847            }
848
849            byte[] swtch = sw(fk1);
850            if (this.mSdes.Presentation.IsVisible)
851            {
852                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
853                {
854                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_sw_output.Text =
855                    Tools.byteArrayToStringWithSpaces(swtch);
856                }
857               , null);
858            }
859
860            byte[] fk2 = fk(swtch, key2);
861            if (this.mSdes.Presentation.IsVisible)
862            {
863                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
864                {
865                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_invers_input.Text =
866                    Tools.byteArrayToStringWithSpaces(fk2);
867                }
868               , null);
869            }                   
870
871            byte[] ciphertext = ip_inverse(fk2);
872            if (this.mSdes.Presentation.IsVisible)
873            {
874                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
875                {
876                    ((SDESPresentation)mSdes.Presentation).encrypt_txt_ip_invers_output.Text =
877                    Tools.byteArrayToStringWithSpaces(ciphertext);
878                }
879               , null);
880            }   
881
882            return ciphertext;
883
884        }//end encrypt
885
886        /// <summary>
887        /// Decrypt-function
888        /// Decrypts the input ciphertext with the given key
889        /// </summary>
890        /// <param name="ciphertext">ciphertext as byte array of size 8</param>
891        /// <param name="key"> key as byte array of size 10</param>
892        /// <returns>plaintext as byte array of size 8</returns>
893        public byte[] decrypt(byte[] ciphertext, byte[] key)
894        {
895            this.mode = 1; // to tell presentation what we are doing
896
897            if (this.mSdes.Presentation.IsVisible)
898            {
899                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
900                {
901                    ((SDESPresentation)mSdes.Presentation).key_txt.Text =
902                    Tools.byteArrayToStringWithSpaces(key);
903                }
904                , null);
905            }
906            //calculate sub key 1
907            byte[] vp10 = p10(key);
908            if (this.mSdes.Presentation.IsVisible)
909            {
910                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
911                {
912                    ((SDESPresentation)mSdes.Presentation).key_txt_p10_input.Text =
913                    Tools.byteArrayToStringWithSpaces(key);
914                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_input_1.Text =
915                    Tools.byteArrayToStringWithSpaces(vp10);
916                }
917                , null);
918            }
919
920            byte[] vls1 = ls_1(vp10);
921            if (this.mSdes.Presentation.IsVisible)
922            {
923                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
924                {
925                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_1_input.Text =
926                    Tools.byteArrayToStringWithSpaces(vls1);
927                }
928                , null);
929            }
930
931            byte[] key1 = p8(vls1);
932            if (this.mSdes.Presentation.IsVisible)
933            {
934                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
935                {
936                    ((SDESPresentation)mSdes.Presentation).key_txt_k1.Text =
937                    Tools.byteArrayToStringWithSpaces(key1);
938                }
939                , null);
940            }
941
942            //calculate sub key 2
943            vls1 = ls_1(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_p10_copy.Text =
949                    Tools.byteArrayToStringWithSpaces(vp10);
950                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_2.Text =
951                    Tools.byteArrayToStringWithSpaces(vp10);
952                    ((SDESPresentation)mSdes.Presentation).key_txt_ls1_3.Text =
953                   Tools.byteArrayToStringWithSpaces(vls1);
954                }
955                , null);
956            }
957
958            vls1 = ls_1(vls1);
959            if (this.mSdes.Presentation.IsVisible)
960            {
961                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
962                {
963                    ((SDESPresentation)mSdes.Presentation).key_txt_p8_2_input.Text =
964                    Tools.byteArrayToStringWithSpaces(vls1);
965                }
966               , null);
967            }
968
969            byte[] key2 = p8(vls1);
970            if (this.mSdes.Presentation.IsVisible)
971            {
972                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
973                {
974                    ((SDESPresentation)mSdes.Presentation).key_txt_k2.Text =
975                    Tools.byteArrayToStringWithSpaces(key2);
976                }
977               , null);
978            }
979
980            // ip_inverse(fk_1(sw(fk_2(ip(ciphertext))))) :
981
982            byte[] ip = this.ip(ciphertext);
983            if (this.mSdes.Presentation.IsVisible)
984            {
985                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
986                {
987                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_plaintext.Text =
988                    Tools.byteArrayToStringWithSpaces(ciphertext);
989                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_input.Text =
990                    Tools.byteArrayToStringWithSpaces(ciphertext);
991                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_output.Text =
992                    Tools.byteArrayToStringWithSpaces(ip);
993                }
994               , null);
995            }
996
997            byte[] fk2 = fk(ip, key2);
998            if (this.mSdes.Presentation.IsVisible)
999            {
1000                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1001                {
1002                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_sw_input.Text =
1003                    Tools.byteArrayToStringWithSpaces(fk2);                 
1004                }
1005               , null);
1006            }
1007
1008            byte[] swtch = sw(fk2); 
1009            if (this.mSdes.Presentation.IsVisible)
1010            {
1011                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1012                {
1013                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_sw_output.Text =
1014                    Tools.byteArrayToStringWithSpaces(swtch);
1015                }
1016               , null);
1017            }
1018
1019            byte[] fk1 = fk(swtch, key1);
1020            if (this.mSdes.Presentation.IsVisible)
1021            {
1022                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1023                {
1024                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_invers_input.Text =
1025                    Tools.byteArrayToStringWithSpaces(fk1);
1026                }
1027               , null);
1028            }
1029
1030            byte[] plaintext = ip_inverse(fk1);
1031            if (this.mSdes.Presentation.IsVisible)
1032            {
1033                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1034                {
1035                    ((SDESPresentation)mSdes.Presentation).decrypt_txt_ip_invers_output.Text =
1036                    Tools.byteArrayToStringWithSpaces(plaintext);
1037                }
1038               , null);
1039            }           
1040
1041            return plaintext;
1042
1043        }//end decrypt
1044
1045        ///<summary>
1046        ///p10-function
1047        ///Permutates the input bytes array of "10 bits" to another by
1048        ///the following rule:
1049        ///
1050        ///src    dest
1051        ///1   -> 3
1052        ///2   -> 5
1053        ///3   -> 2
1054        ///4   -> 7
1055        ///5   -> 4
1056        ///6   -> 10
1057        ///7   -> 1
1058        ///8   -> 9
1059        ///9   -> 8
1060        ///10  -> 6
1061        ///</summary>
1062        ///<param name="bits">byte array of size 10</param>
1063        ///<returns>byte array of size 10</returns>
1064        ///
1065        private byte[] p10(byte[] bits)
1066        {
1067
1068            byte[] p10 = new byte[10];
1069
1070            p10[1 - 1] = bits[3 - 1];
1071            p10[2 - 1] = bits[5 - 1];
1072            p10[3 - 1] = bits[2 - 1];
1073            p10[4 - 1] = bits[7 - 1];
1074            p10[5 - 1] = bits[4 - 1];
1075            p10[6 - 1] = bits[10 - 1];
1076            p10[7 - 1] = bits[1 - 1];
1077            p10[8 - 1] = bits[9 - 1];
1078            p10[9 - 1] = bits[8 - 1];
1079            p10[10 - 1] = bits[6 - 1];
1080
1081            //mSdes.GuiLogMessage("P10 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(p10), NotificationLevel.Debug);
1082            return p10;
1083
1084        }//end p10
1085
1086        ///<summary>
1087        ///p8-function
1088        ///Permutates the input bytes array of "8 bits" to another by
1089        ///the following rule:
1090        ///
1091        ///src    dest
1092        ///1   -> 6
1093        ///2   -> 3
1094        ///3   -> 7
1095        ///4   -> 4
1096        ///5   -> 8
1097        ///6   -> 5
1098        ///7   -> 10
1099        ///8   -> 9
1100        ///</summary>
1101        ///<param name="bits">byte array of size 10</param>
1102        ///<returns>byte array of size 8</returns>
1103        private byte[] p8(byte[] bits)
1104        {
1105
1106            byte[] p8 = new byte[8];
1107
1108            p8[1 - 1] = bits[6 - 1];
1109            p8[2 - 1] = bits[3 - 1];
1110            p8[3 - 1] = bits[7 - 1];
1111            p8[4 - 1] = bits[4 - 1];
1112            p8[5 - 1] = bits[8 - 1];
1113            p8[6 - 1] = bits[5 - 1];
1114            p8[7 - 1] = bits[10 - 1];
1115            p8[8 - 1] = bits[9 - 1];
1116
1117            //mSdes.GuiLogMessage("P8 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(p8), NotificationLevel.Debug);
1118            return p8;
1119
1120        }//end p8
1121
1122        ///<summary>
1123        ///ip-function (initial permutation)
1124        ///Permutates the input array of "8 bits" to another by
1125        ///the following rule:
1126        ///
1127        ///src    dest
1128        ///1   -> 2
1129        ///2   -> 6
1130        ///3   -> 3
1131        ///4   -> 1
1132        ///5   -> 4
1133        ///6   -> 8
1134        ///7   -> 5
1135        ///8   -> 7
1136        ///</summary>
1137        ///<param name="bits">byte array of size 8</param>
1138        ///<returns>byte array of size 8</returns>
1139        private byte[] ip(byte[] bits)
1140        {
1141
1142            byte[] ip = new byte[8];
1143
1144            ip[1 - 1] = bits[2 - 1];
1145            ip[2 - 1] = bits[6 - 1];
1146            ip[3 - 1] = bits[3 - 1];
1147            ip[4 - 1] = bits[1 - 1];
1148            ip[5 - 1] = bits[4 - 1];
1149            ip[6 - 1] = bits[8 - 1];
1150            ip[7 - 1] = bits[5 - 1];
1151            ip[8 - 1] = bits[7 - 1];
1152
1153            //mSdes.GuiLogMessage("ip with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ip), NotificationLevel.Debug);
1154            return ip;
1155
1156        }//end ip
1157
1158        ///<summary>
1159        ///ip^-1-function (initial permutation inverse)
1160        ///Permutates the input array of "8 bits" to another by
1161        ///the following rule:
1162        ///
1163        ///src    dest
1164        ///1   -> 4
1165        ///2   -> 1
1166        ///3   -> 3
1167        ///4   -> 5
1168        ///5   -> 7
1169        ///6   -> 2
1170        ///7   -> 8
1171        ///8   -> 6
1172        ///</summary>
1173        ///<param name="bits">byte array of size 8</param>
1174        ///<returns>byte array of size 8</returns>
1175        private byte[] ip_inverse(byte[] bits)
1176        {
1177
1178            byte[] ip_inverse = new byte[8];
1179
1180            ip_inverse[1 - 1] = bits[4 - 1];
1181            ip_inverse[2 - 1] = bits[1 - 1];
1182            ip_inverse[3 - 1] = bits[3 - 1];
1183            ip_inverse[4 - 1] = bits[5 - 1];
1184            ip_inverse[5 - 1] = bits[7 - 1];
1185            ip_inverse[6 - 1] = bits[2 - 1];
1186            ip_inverse[7 - 1] = bits[8 - 1];
1187            ip_inverse[8 - 1] = bits[6 - 1];
1188
1189            //mSdes.GuiLogMessage("ip_inverse with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ip_inverse), NotificationLevel.Debug);             
1190            return ip_inverse;
1191
1192        }//end ip_inverse
1193
1194        ///<summary>
1195        ///fk-function
1196        ///
1197        ///combines the following functions:
1198        ///
1199        ///right is the right part of the input array
1200        ///left is the left part of the input array
1201        ///
1202        ///(right | left) := (inputarray))
1203        ///ret := exclusive_or(left,F(right,key)) + right)
1204        ///</summary>
1205        ///<param name="bits">byte array of size 8</param>
1206        ///<param name="key">byte array of size 8</param>
1207        ///<returns>byte array of size 8</returns>
1208        private byte[] fk(byte[] bits, byte[] key)
1209        {
1210            byte[] left = { bits[1 - 1], bits[2 - 1], bits[3 - 1], bits[4 - 1] };
1211            byte[] right = { bits[5 - 1], bits[6 - 1], bits[7 - 1], bits[8 - 1] };
1212
1213            byte[] exclusive_oder = Tools.exclusive_or(left, F(right, key));
1214
1215            byte[] ret = {exclusive_oder[1-1],exclusive_oder[2-1],exclusive_oder[3-1],exclusive_oder[4-1],
1216                                     right[1-1],right[2-1],right[3-1],right[4-1]};
1217
1218            fkstep++;
1219            if (fkstep == 2)
1220                fkstep = 0;
1221
1222            //mSdes.GuiLogMessage("fk with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);
1223            return ret;
1224
1225        }//end fk
1226
1227        ///<summary>
1228        ///ls-1 function
1229        ///</summary>
1230        ///<param name="bits">byte array of size 10</param>
1231        ///<returns>byte array of size 10</returns>
1232        private byte[] ls_1(byte[] bits)
1233        {
1234
1235            byte[] ls_1 = new byte[10];
1236
1237            ls_1[1 - 1] = bits[2 - 1];
1238            ls_1[2 - 1] = bits[3 - 1];
1239            ls_1[3 - 1] = bits[4 - 1];
1240            ls_1[4 - 1] = bits[5 - 1];
1241            ls_1[5 - 1] = bits[1 - 1];
1242            ls_1[6 - 1] = bits[7 - 1];
1243            ls_1[7 - 1] = bits[8 - 1];
1244            ls_1[8 - 1] = bits[9 - 1];
1245            ls_1[9 - 1] = bits[10 - 1];
1246            ls_1[10 - 1] = bits[6 - 1];
1247
1248            //mSdes.GuiLogMessage("ls-1 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ls_1), NotificationLevel.Debug);
1249            return ls_1;
1250
1251        }//end ls_1
1252
1253        ///<summary>
1254        ///switch-function
1255        ///
1256        ///switches the left side and the right side of the 8 bit array
1257        ///(left|right) -> (right|left)
1258        ///</summary>
1259        ///<param name="bits">byte array of size 8</param>
1260        ///<returns>byte array of size 8</returns>
1261        private byte[] sw(byte[] bits)
1262        {
1263
1264            byte[] ret = {bits[5-1],bits[6-1],bits[7-1],bits[8-1],
1265                                         bits[1-1],bits[2-1],bits[3-1],bits[4-1]};
1266
1267            //mSdes.GuiLogMessage("sw with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);
1268            return ret;
1269
1270        }//end sw
1271
1272        ///<summary>
1273        ///F-function
1274        ///
1275        ///combines both s-boxes and permutates the return value with p4
1276        ///p4( s0(exclusive_or(ep(number),key) | s1(exclusive_or(ep(number),key) )
1277        ///</summary>
1278        ///<param name="bits">byte array of size 8</param>
1279        ///<param name="bits">key of size 8</param>
1280        ///<returns>byte array of size 8</returns>
1281        private byte[] F(byte[] bits, byte[] key)
1282        {
1283
1284            byte[] ep = this.ep(bits);
1285
1286            byte[] exclusive = Tools.exclusive_or(ep, key);
1287
1288            byte[] s0_input = { exclusive[1 - 1], exclusive[2 - 1], exclusive[3 - 1], exclusive[4 - 1] };
1289            byte[] s0 = sbox_0(s0_input);
1290
1291            byte[] s1_input = { exclusive[5 - 1], exclusive[6 - 1], exclusive[7 - 1], exclusive[8 - 1] };
1292            byte[] s1 = sbox_1(s1_input);
1293
1294            byte[] s0_s1 = { s0[1 - 1], s0[2 - 1], s1[1 - 1], s1[2 - 1] };
1295            byte[] ret = p4(s0_s1);
1296
1297            if (this.mSdes.Presentation.IsVisible)
1298            {
1299                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1300                {
1301                    if (mode == 0 && fkstep == 0)
1302                    {
1303                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_sbox1_output.Text =
1304                        Tools.byteArrayToStringWithSpaces(ret);
1305                    }
1306                    if (mode == 0 && fkstep == 1)
1307                    {
1308                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_sbox2_output.Text =
1309                        Tools.byteArrayToStringWithSpaces(ret);
1310                    }
1311                    if (mode == 1 && fkstep == 0)
1312                    {
1313                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_sbox1_output.Text =
1314                        Tools.byteArrayToStringWithSpaces(ret);
1315                    }
1316                    if (mode == 1 && fkstep == 1)
1317                    {
1318                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_sbox2_output.Text =
1319                        Tools.byteArrayToStringWithSpaces(ret);
1320                    }
1321                }
1322               , null);
1323            }
1324
1325            //mSdes.GuiLogMessage("F with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(key) + " ist " + Tools.intArray2String(ret), NotificationLevel.Debug);
1326            return ret;
1327
1328        }//end F
1329
1330        ///<summary>
1331        ///p4-function
1332        ///Permutates the input array of "4 bits" to another by
1333        ///the following rule:
1334        ///
1335        ///src    dest
1336        ///1   -> 2
1337        ///2   -> 4
1338        ///3   -> 3
1339        ///4   -> 1
1340        ///</summary>
1341        ///<param name="bits">byte array of size 4</param>
1342        ///<returns>byte array of size 4</returns>
1343        private byte[] p4(byte[] bits)
1344        {
1345
1346            byte[] ret = new byte[4];
1347            ret[1 - 1] = bits[2 - 1];
1348            ret[2 - 1] = bits[4 - 1];
1349            ret[3 - 1] = bits[3 - 1];
1350            ret[4 - 1] = bits[1 - 1];
1351
1352            return ret;
1353
1354        }//end p4
1355
1356        ///<summary>
1357        ///ep-function
1358        ///Permutates the input array of "4 bits" to another array of "8 bits" by
1359        ///the following rule:
1360        ///
1361        ///src    dest
1362        ///1   -> 4
1363        ///2   -> 1
1364        ///3   -> 2
1365        ///4   -> 3
1366        ///5   -> 2
1367        ///6   -> 3
1368        ///7   -> 4
1369        ///8   -> 1
1370        ///</summary>
1371         ///<param name="bits">byte array of size 4</param>
1372        ///<returns>byte array of size 8</returns>
1373        private byte[] ep(byte[] bits)
1374        {
1375
1376            byte[] ep = new byte[8];
1377            ep[1 - 1] = bits[4 - 1];
1378            ep[2 - 1] = bits[1 - 1];
1379            ep[3 - 1] = bits[2 - 1];
1380            ep[4 - 1] = bits[3 - 1];
1381            ep[5 - 1] = bits[2 - 1];
1382            ep[6 - 1] = bits[3 - 1];
1383            ep[7 - 1] = bits[4 - 1];
1384            ep[8 - 1] = bits[1 - 1];
1385
1386            if (this.mSdes.Presentation.IsVisible)
1387            {
1388                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1389                {
1390                    if (mode == 0 && fkstep == 0)
1391                    {
1392                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_ep_output.Text =
1393                        Tools.byteArrayToStringWithSpaces(ep);
1394                    }
1395                    if (mode == 0 && fkstep == 1)
1396                    {
1397                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_ep_output1.Text =
1398                        Tools.byteArrayToStringWithSpaces(ep);
1399                    }
1400                    if (mode == 1 && fkstep == 0)
1401                    {
1402                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_ep_output.Text =
1403                        Tools.byteArrayToStringWithSpaces(ep);
1404                    }
1405                    if (mode == 1 && fkstep == 1)
1406                    {
1407                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_ep_output1.Text =
1408                        Tools.byteArrayToStringWithSpaces(ep);
1409                    }
1410                }
1411               , null);
1412            }
1413
1414            return ep;
1415        }
1416
1417        ///<summary>
1418        ///SBox-0
1419        ///
1420        ///S0 =  1 0 3 2
1421        ///      3 2 1 0
1422        ///      0 2 1 3   
1423        ///      3 1 3 2           
1424        ///</summary>
1425        ///<param name="bits">byte array of size 4</param>
1426        ///<returns>byte array of size 2</returns>
1427        private byte[] sbox_0(byte[] bits)
1428        {
1429
1430            int row = 2 * bits[1 - 1] + 1 * bits[4 - 1];
1431            int column = 2 * bits[2 - 1] + 1 * bits[3 - 1];
1432
1433            byte[,][] sbox_0 = new byte[4, 4][]
1434                            {
1435                            {new byte[] {0,1}, new byte[] {0,0}, new byte[] {1,1}, new byte[] {1,0}},
1436                                                {new byte[] {1,1}, new byte[] {1,0}, new byte[] {0,1}, new byte[] {0,0}},
1437                                                {new byte[] {0,0}, new byte[] {1,0}, new byte[] {0,1}, new byte[] {1,1}},
1438                                                {new byte[] {1,1}, new byte[] {0,1}, new byte[] {1,1}, new byte[] {1,0}}
1439                            };
1440
1441            byte[] ret = sbox_0[row, column];
1442
1443            if (this.mSdes.Presentation.IsVisible)
1444            {
1445                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1446                {
1447                    if (mode == 0 && fkstep == 0)
1448                    {
1449                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s0_1_output.Text =
1450                        Tools.byteArrayToStringWithSpaces(ret);
1451                    }
1452                    if (mode == 0 && fkstep == 1)
1453                    {
1454                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s0_2_output.Text =
1455                        Tools.byteArrayToStringWithSpaces(ret);
1456                    }
1457                    if (mode == 1 && fkstep == 0)
1458                    {
1459                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s0_1_output.Text =
1460                        Tools.byteArrayToStringWithSpaces(ret);
1461                    }
1462                    if (mode == 1 && fkstep == 1)
1463                    {
1464                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s0_2_output.Text =
1465                        Tools.byteArrayToStringWithSpaces(ret);
1466                    }
1467                }
1468               , null);
1469            }
1470
1471            //mSdes.GuiLogMessage("S0 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);
1472            return ret;
1473
1474        }//end sbox-0
1475
1476
1477        ///<summary>
1478        ///SBox-1
1479        ///
1480        ///S1 =  0 1 2 3
1481        ///      2 0 1 3
1482        ///      3 0 1 0
1483        ///      2 1 0 3
1484        ///</summary>
1485        ///<param name="bits">byte array of size 4</param>
1486        ///<returns>byte array of size 2</returns>
1487        private byte[] sbox_1(byte[] bits)
1488        {
1489
1490            int row = 2 * bits[1 - 1] + 1 * bits[4 - 1];
1491            int column = 2 * bits[2 - 1] + 1 * bits[3 - 1];
1492
1493            byte[,][] sbox_1 = new byte[4, 4][]
1494                            {
1495                            {new byte[] {0,0}, new byte[] {0,1}, new byte[] {1,0}, new byte[] {1,1}},
1496                                                        {new byte[] {1,0}, new byte[] {0,0}, new byte[] {0,1}, new byte[] {1,1}},
1497                                                        {new byte[] {1,1}, new byte[] {0,0}, new byte[] {0,1}, new byte[] {0,0}},
1498                                                        {new byte[] {1,0}, new byte[] {0,1}, new byte[] {0,0}, new byte[] {1,1}}
1499                            };
1500
1501            byte[] ret = sbox_1[row, column];
1502
1503            if (this.mSdes.Presentation.IsVisible)
1504            {
1505                ((SDESPresentation)mSdes.Presentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1506                {
1507                    if (mode == 0 && fkstep == 0)
1508                    {
1509                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s1_1_output.Text =
1510                        Tools.byteArrayToStringWithSpaces(ret);
1511                    }
1512                    if (mode == 0 && fkstep == 1)
1513                    {
1514                        ((SDESPresentation)mSdes.Presentation).encrypt_txt_s1_2_output.Text =
1515                        Tools.byteArrayToStringWithSpaces(ret);
1516                    }
1517                    if (mode == 1 && fkstep == 0)
1518                    {
1519                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s1_1_output.Text =
1520                        Tools.byteArrayToStringWithSpaces(ret);
1521                    }
1522                    if (mode == 1 && fkstep == 1)
1523                    {
1524                        ((SDESPresentation)mSdes.Presentation).decrypt_txt_s1_2_output.Text =
1525                        Tools.byteArrayToStringWithSpaces(ret);
1526                    }
1527                }
1528               , null);
1529            }
1530
1531            //mSdes.GuiLogMessage("S1 with " + Tools.intArray2String(bits) + " is " + Tools.intArray2String(ret), NotificationLevel.Debug);             
1532            return ret;
1533
1534        }//end sbox-1
1535
1536    }
1537
1538    ///<summary>
1539    ///Encapsulates some necessary functions
1540    ///</summary>
1541    public class Tools
1542    {
1543
1544        /// <summary>
1545        /// transforms a byte array into a String with spaces after each byte
1546        /// example:
1547        ///     1,0 => "1 0"
1548        /// </summary>
1549        /// <param name="byt">byt</param>
1550        /// <returns>s</returns>
1551        public static String byteArrayToStringWithSpaces(byte[] byt)
1552        {
1553            String s = "";
1554
1555            foreach (byte b in byt)
1556            {
1557                s = s + b + " ";
1558            }
1559            return s;
1560        }
1561        ///<summary>
1562        ///Converts an byte array to a String
1563        ///</summary>
1564        ///<param name="bits">byte array of size n</param>
1565        ///<returns>String</returns>
1566        public static String byteArray2String(byte[] bits)
1567        {
1568
1569            String ret = "";
1570            for (int i = 0; i < bits.Length; i++)
1571            {
1572                ret += ("" + bits[i]);
1573            }
1574            return ret;
1575
1576        }//end byteArray2String
1577
1578        ///<summary>
1579        ///Converts the given byte array to a printable String
1580        ///
1581        ///example {72, 101, 108, 108, 111} -> "Hello"
1582        ///</summary>
1583        ///<param name="bits">byte array of size n</param>
1584        ///<returns>String</returns>
1585        public static String byteArray2PrintableString(byte[] bits)
1586        {
1587
1588            String ret = "";
1589            for (int i = 0; i < bits.Length; i++)
1590            {
1591                ret += ("" + (char)bits[i]);
1592            }
1593            return ret;
1594
1595        }// byteArray2PrintableString
1596
1597        ///<summary>
1598        ///equals-function
1599        ///
1600        ///returns true if both integer arrays are equal
1601        ///</summary>
1602        ///<param name="a">byte array of size n</param>
1603        ///<param name="b">byte array of size n</param>
1604        ///<returns>bool</returns>
1605        public static bool byteArrays_Equals(byte[] a, byte[] b)
1606        {
1607
1608            for (int i = 0; i < a.Length; i++)
1609            {
1610                if (a[i] != b[i])
1611                {
1612                    return false;
1613                }
1614            }
1615
1616            return true;
1617
1618        }//end byteArrays_Equals       
1619
1620        ///<summary>
1621        ///converts an Byte to an byte array of (0,1)
1622        ///
1623        ///100 -> {1,1,0,0,1,0,0}
1624        ///</summary>
1625        ///<param name="byt">byte array of size n</param>
1626        ///<returns>byte array</returns>
1627        public static byte[] byteToByteArray(byte byt)
1628        {
1629
1630            byte[] bytearray = new byte[8];
1631
1632            for (int i = 7; i >= 0; i--)
1633            {
1634
1635                bytearray[i] = (byte)(byt % 2);
1636                byt = (byte)Math.Floor((double)(byt / 2));
1637
1638            }
1639
1640            return bytearray;
1641
1642        }//end byteTointArray
1643
1644        ///<summary>
1645        ///converts an byte array of (0,1) to an byte
1646        ///
1647        ///{1,1,0,0,1,0,0} -> 100
1648        ///</summary>
1649        ///<param name="bytearray">byte array of size n</param>
1650        ///<returns>byte</returns>
1651        public static byte byteArrayToByte(byte[] bytearray)
1652        {
1653
1654            int byt = 0;
1655
1656            byt = (bytearray[0] * 128)
1657                        + (bytearray[1] * 64)
1658                        + (bytearray[2] * 32)
1659                        + (bytearray[3] * 16)
1660                        + (bytearray[4] * 8)
1661                        + (bytearray[5] * 4)
1662                        + (bytearray[6] * 2)
1663                        + (bytearray[7] * 1);
1664
1665            return (byte)byt;
1666
1667        }//end byteArrayToInteger
1668
1669        ///<summary>
1670        ///Exclusiv-OR function
1671        ///
1672        ///Does a exlusiv-or on two byte arrays
1673        ///
1674        ///example {1,0,1} XOR {1,0,0} -> {0,0,1}
1675        ///</summary>
1676        ///<param name="bitsA">byte array of size n</param>
1677        ///<param name="bitsB">byte array of size n</param>
1678        ///<returns>byte array of size n</returns>
1679        public static byte[] exclusive_or(byte[] bitsA, byte[] bitsB)
1680        {
1681
1682            byte[] exclusive_or_AB = new byte[bitsA.Length];
1683
1684            for (int i = 0; i < bitsA.Length; i++)
1685            {
1686
1687                if ((bitsA[i] == 0 && bitsB[i] == 1) ||
1688                   (bitsA[i] == 1 && bitsB[i] == 0)
1689                )
1690                {
1691                    exclusive_or_AB[i] = 1;
1692                }
1693                else
1694                {
1695                    exclusive_or_AB[i] = 0;
1696                }//end if
1697
1698            }//end for
1699
1700            return exclusive_or_AB;
1701
1702        }//end exclusive_or
1703
1704        ///<summary>
1705        ///converts string to an byte array
1706        ///
1707        ///example "Hello" -> {72, 101, 108, 108, 111}
1708        ///</summary>
1709        ///<param name="s">String</param>
1710        ///<returns>byte array</returns>
1711        public static byte[] stringToByteArray(String s)
1712        {
1713            byte[] bytearray = new byte[s.Length];
1714
1715            for (int i = 0; i < s.Length; i++)
1716            {
1717                bytearray[i] = (byte)s[i];
1718            }
1719
1720            return bytearray;
1721
1722        }// end stringToByteArray
1723
1724        ///<summary>
1725        ///converts a binary string to an byte array
1726        ///
1727        ///example "10010" -> {1, 0, 0, 1, 0}
1728        ///</summary>
1729        ///<param name="s">String</param>
1730        ///<returns>byte array</returns>
1731        public static byte[] stringToBinaryByteArray(String s)
1732        {
1733            byte[] bytearray = new byte[s.Length];
1734
1735            for (int i = 0; i < s.Length; i++)
1736            {
1737                if (s[i] == '1')
1738                {
1739                    bytearray[i] = 1;
1740                }
1741                else if (s[i] == '0')
1742                {
1743                    bytearray[i] = 0;
1744                }
1745                else
1746                {
1747                    throw new Exception("Invalid Character '" + s[i] + "' at position " + i + " in String which represents binary values: " + s);
1748                }
1749            }
1750
1751            return bytearray;
1752
1753        }// end stringToByteArray
1754    }
1755
1756    ///<summary>
1757    ///Encapsulates the CipherBlockChaining algorithm
1758    ///</summary>
1759    public class CipherBlockChaining
1760    {
1761
1762        private SDES mSdes;
1763        private SDES_algorithm mAlgorithm;
1764
1765        /// <summary>
1766        /// Constructs a CipherBlockChaining for SDES
1767        /// </summary>
1768        /// <param name="sdes">plugin</param>
1769        public CipherBlockChaining(SDES sdes)
1770        {
1771            this.mSdes = sdes;
1772            this.mAlgorithm = new SDES_algorithm(sdes);
1773        }
1774
1775        ///<summary>
1776        ///Encrypts the given plaintext with the given key
1777        ///using CipherBlockChaining
1778        ///</summary>
1779        public void encrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key, byte[] vector)
1780        {
1781
1782            byte[] buffer = new byte[1];
1783            int position = 0;
1784
1785            while (!this.mSdes.getStop() && (inputstream.Read(buffer, 0, 1)) > 0)
1786            {
1787                //Step 1 get plaintext symbol
1788                byte symbol = buffer[0];
1789                //Step 2 exclusiv OR with vector
1790                vector = Tools.exclusive_or(vector, Tools.byteToByteArray(symbol));
1791                //Step 3 decrypt vector with key
1792                vector = mAlgorithm.encrypt(vector, key);
1793                //Step 4 store symbol in ciphertext
1794                outputstream.Write(Tools.byteArrayToByte(vector));
1795
1796                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1797                {
1798                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1799                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1800                }
1801                outputstream.Flush();
1802            }
1803
1804        }//end encrypt
1805
1806        ///
1807        ///Encrypts the given plaintext with the given key
1808        ///using CipherBlockChaining
1809        ///
1810        /// bytesToUse tells the algorithm how many bytes it has to encrypt
1811        /// bytesToUse = 0 => encrypt all
1812        public byte[] encrypt(byte[] input, byte[] key, byte[] vector, [Optional, DefaultParameterValue(0)] int bytesToUse)
1813        {
1814            int until = input.Length;           
1815
1816            if (bytesToUse < until && bytesToUse > 0)
1817                until = bytesToUse;
1818
1819            byte[] output = new byte[until];
1820
1821            for (int i = 0; i < until; i++)
1822            {
1823                vector = Tools.exclusive_or(vector, Tools.byteToByteArray(input[i]));
1824                vector = mAlgorithm.encrypt(vector, key);
1825                output[i] = Tools.byteArrayToByte(vector);
1826
1827            }//end while
1828           
1829            return output;
1830
1831        }//end encrypt
1832
1833        ///<summary>
1834        ///Decrypts the given plaintext with the given Key
1835        ///using CipherBlockChaining
1836        ///</summary>
1837        public void decrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key, byte[] vector)
1838        {
1839
1840            byte[] buffer = new byte[1];
1841            int position = 0;
1842
1843            while (!this.mSdes.getStop() && (inputstream.Read(buffer, 0, 1)) > 0)
1844            {
1845                //Step 1 get Symbol of Ciphertext
1846                byte symbol = buffer[0];
1847                //Step 2 Decrypt symbol with key and exclusiv-or with vector
1848                outputstream.Write((Tools.byteArrayToByte(Tools.exclusive_or(mAlgorithm.decrypt(Tools.byteToByteArray(symbol), key), vector))));
1849                //Step 3 let vector be the decrypted Symbol
1850                vector = Tools.byteToByteArray(buffer[0]);
1851
1852                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1853                {
1854                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1855                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1856                }
1857                outputstream.Flush();
1858            }
1859
1860        }//end decrypt
1861
1862        ///
1863        ///Decrypt the given plaintext with the given key
1864        ///using CipherBlockChaining
1865        ///
1866        /// bytesToUse tells the algorithm how many bytes it has to encrypt
1867        /// bytesToUse = 0 => encrypt all
1868        public byte[] decrypt(byte[] input, byte[] key, byte[] vector, [Optional, DefaultParameterValue(0)] int bytesToUse)
1869        {
1870
1871            int until = input.Length;
1872           
1873            if (bytesToUse < until && bytesToUse > 0)
1874                until = bytesToUse;
1875
1876            byte[] output = new byte[until];
1877
1878            for (int i = 0; i < until; i++)
1879            {
1880                output[i] = (Tools.byteArrayToByte(Tools.exclusive_or(mAlgorithm.decrypt(Tools.byteToByteArray(input[i]), key), vector)));
1881                vector = Tools.byteToByteArray(input[i]);
1882                           
1883            }//end while
1884
1885            return output;
1886
1887        }//end encrypt
1888
1889    }//end class CipherBlockChaining
1890
1891    ///<summary>
1892    ///Encapsulates the ElectronicCodeBook algorithm
1893    ///</summary>
1894    public class ElectronicCodeBook
1895    {
1896
1897        private SDES mSdes;
1898        private SDES_algorithm mAlgorithm;
1899
1900        /// <summary>
1901        /// Constructs a ElectronicCodeBook for SDES
1902        /// </summary>
1903        /// <param name="sdes">plugin</param>
1904        public ElectronicCodeBook(SDES sdes)
1905        {
1906            this.mSdes = sdes;
1907            this.mAlgorithm = new SDES_algorithm(sdes);
1908        }
1909
1910        ///
1911        ///Encrypts the given plaintext with the given key
1912        ///using ElectronicCodeBookMode
1913        ///
1914        public void encrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key)
1915        {
1916
1917            byte[] buffer = new byte[1];
1918            int position = 0;
1919
1920            while (!this.mSdes.getStop() && (inputstream.Read(buffer, 0, 1)) > 0)
1921            {
1922                //Step 1 get plaintext symbol
1923                byte symbol = buffer[0]; ;
1924                //Step 2 encrypt symbol
1925                outputstream.Write(Tools.byteArrayToByte(this.mAlgorithm.encrypt(Tools.byteToByteArray(symbol), key)));
1926
1927                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1928                {
1929                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1930                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1931                }
1932                outputstream.Flush();
1933
1934            }//end while
1935
1936        }//end encrypt
1937
1938        ///
1939        ///Encrypts the given plaintext with the given key
1940        ///using ElectronicCodeBookMode
1941        ///
1942        /// bytesToUse tells the algorithm how many bytes it has to encrypt
1943        /// bytesToUse = 0 => encrypt all
1944        public byte[] encrypt(byte[] input, byte[] key, [Optional, DefaultParameterValue(0)] int bytesToUse)
1945        {
1946
1947            int until = input.Length;
1948
1949            if(bytesToUse < until && bytesToUse > 0)
1950                until = bytesToUse;
1951
1952            byte[] output = new byte[until];
1953
1954            for(int i=0;i<until;i++)
1955            {               
1956                //Step 2 encrypt symbol
1957                output[i] = Tools.byteArrayToByte(this.mAlgorithm.encrypt(Tools.byteToByteArray(input[i]), key));
1958
1959            }//end while
1960
1961            return output;
1962
1963        }//end encrypt
1964
1965        ///<summary>
1966        ///Decrypts the given plaintext with the given Key
1967        ///using ElectronicCodeBook mode
1968        ///</summary>
1969        public void decrypt(CryptoolStream inputstream, CryptoolStream outputstream, byte[] key)
1970        {
1971
1972            byte[] buffer = new byte[1];
1973            int position = 0;
1974
1975            while (!this.mSdes.getStop() && (inputstream.Read(buffer, 0, 1)) > 0)
1976            {
1977                //Step 1 get plaintext symbol
1978                byte symbol = buffer[0];
1979                //Step 2 encrypt symbol
1980                outputstream.Write(Tools.byteArrayToByte(this.mAlgorithm.decrypt(Tools.byteToByteArray(symbol), key)));
1981
1982                if ((int)(inputstream.Position * 100 / inputstream.Length) > position)
1983                {
1984                    position = (int)(inputstream.Position * 100 / inputstream.Length);
1985                    mSdes.ProgressChanged(inputstream.Position, inputstream.Length);
1986                }
1987                outputstream.Flush();
1988
1989            }//end while
1990
1991        }//end decrypt
1992
1993        ///
1994        ///Decrypt the given plaintext with the given key
1995        ///using ElectronicCodeBookMode
1996        ///
1997        /// bytesToUse tells the algorithm how many bytes it has to decrypt
1998        /// bytesToUse = 0 => encrypt all
1999        public byte[] decrypt(byte[] input, byte[] key, [Optional, DefaultParameterValue(0)] int bytesToUse)
2000        {
2001            int until = input.Length;
2002
2003            if (bytesToUse < until && bytesToUse > 0)
2004                until = bytesToUse;
2005           
2006            byte[] output = new byte[until];
2007
2008            for (int i = 0; i < until; i++)
2009            {
2010                //Step 2 encrypt symbol
2011                output[i] = Tools.byteArrayToByte(this.mAlgorithm.decrypt(Tools.byteToByteArray(input[i]), key));
2012
2013            }//end while
2014
2015            return output;
2016
2017        }//end encrypt
2018
2019    }//end class ElectronicCodeBook
2020
2021}//end namespace Cryptool.Plugins.Cryptography.Encryption
Note: See TracBrowser for help on using the repository browser.