source: trunk/CrypPlugins/DES/DES.cs @ 1162

Last change on this file since 1162 was 1162, checked in by Arno Wacker, 12 years ago

KeySearcher:

  • Removed creation of CryptoolStream for each trial key -> performance boost
  • Re-integrated the usage of only the partial encrypted message for trial decryption (byteToUse). Now the value set in the costFunction will determine how many bytes will be used. This value shall be moved in the future to the KeySearcher settings.

IControlEncryption

  • Added an extended method for Decrypt to IControlEncryption for usage with bytesToUse

AES/DES/SDES

  • Updated for compatibility with IControlEncryption-changes (the new parameter is also used by all three)

Samples

  • Updated KeySearcher-Sample-DES to use only 128 bytes for bruteforcing instead of 256 (increase performance a little)

Note: providing a value for bytesToUse smaller than the blocksize of the algorithm used is an error case - not sure if every case is already covered.

File size: 23.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.IO;
6using System.Security.Cryptography;
7using Cryptool.PluginBase;
8using System.ComponentModel;
9using Cryptool.PluginBase.Cryptography;
10using Cryptool.PluginBase.IO;
11using System.Windows.Controls;
12using Cryptool.PluginBase.Control;
13using System.Reflection;
14// Reference to the CubeAttackController interface (own dll)
15using Cryptool.CubeAttackController;
16
17namespace Cryptool.Plugins.Cryptography.Encryption
18{
19    [Author("Dr. Arno Wacker", "arno.wacker@cryptool.org", "Uni Duisburg", "http://www.uni-duisburg-essen.de")]
20    [PluginInfo(false, "DES", "Data Encryption Standard", "DES/DetailedDescription/Description.xaml", "DES/icon.png", "DES/Images/encrypt.png", "DES/Images/decrypt.png")]
21    [EncryptionType(EncryptionType.SymmetricBlock)]
22    public class DES : IEncryption
23    {
24        #region Private variables
25        private DESSettings settings;
26        private CryptoolStream inputStream;
27        private CryptoolStream outputStream;
28        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
29        private byte[] inputKey;
30        private byte[] inputIV;
31        private CryptoStream p_crypto_stream;
32        private bool stop = false;
33        private IControlEncryption controlSlave;
34        #endregion
35
36
37        #region Initialisation
38       
39        public DES()
40        {
41            this.settings = new DESSettings();
42        }
43
44
45       
46
47        #endregion
48
49        #region External connection properties
50
51        [PropertyInfo(Direction.ControlSlave, "DES Slave for Cryptanalysis", "Direct access to the DES component for cryptanalysis.", "", DisplayLevel.Beginner)]
52        public IControlEncryption ControlSlave
53        {
54            get
55            {
56                if (controlSlave == null)
57                    controlSlave = new DESControl(this);
58                return controlSlave;
59            }
60        }
61
62        private IControlCubeAttack desSlave;
63        [PropertyInfo(Direction.ControlSlave, "DES Slave for cube attack", "Direct access to the DES component for usage with the cube attack plugin.", "", DisplayLevel.Beginner)]
64        public IControlCubeAttack DESSlave
65        {
66            get
67            {
68                if (desSlave == null)
69                    desSlave = new CubeAttackControl(this);
70                return desSlave;
71            }
72        }
73
74
75        [PropertyInfo(Direction.InputData, "Input", "Data to be encrypted or decrypted", null, true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
76        public CryptoolStream InputStream
77        {
78            get 
79            {
80                if (inputStream != null)
81                {
82                    CryptoolStream cs = new CryptoolStream();
83                    cs.OpenRead(inputStream.FileName);
84                    listCryptoolStreamsOut.Add(cs);
85                    return cs;
86                }
87                else return null;
88            }
89            set 
90            { 
91              this.inputStream = value;
92              if (value != null) listCryptoolStreamsOut.Add(value);
93              OnPropertyChanged("InputStream");
94            }
95        }
96
97        [PropertyInfo(Direction.InputData, "Key", "The key for encryption7decryption. It must be exactly 8 bytes (64 Bits).", null, true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
98        public byte[] InputKey
99        {
100            get { return this.inputKey; }
101            set
102            {
103                this.inputKey = value;
104                OnPropertyChanged("InputKey");
105            }
106        }
107
108        [PropertyInfo(Direction.InputData, "IV", "IV to be used in chaining modes, must be the same as the Blocksize in bytes (8 bytes).", null, false, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
109        public byte[] InputIV
110        {
111            get { return this.inputIV; }
112            set
113            {
114                this.inputIV = value;
115                OnPropertyChanged("InputIV");
116            }
117        }
118       
119        [PropertyInfo(Direction.OutputData, "Output stream", "Encrypted or decrypted output data", null, true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
120        public CryptoolStream OutputStream
121        {
122            get
123            {
124                if (this.outputStream != null)
125                {
126                    CryptoolStream cs = new CryptoolStream();
127                    listCryptoolStreamsOut.Add(cs);
128                    cs.OpenRead(this.outputStream.FileName);
129                    return cs;
130                }
131                return null;
132            }
133            set
134            {
135                outputStream = value;
136                if (value != null) listCryptoolStreamsOut.Add(value);
137                OnPropertyChanged("OutputStream");
138            }
139        }
140
141        #endregion       
142
143        #region Public IPlugin Member
144
145        #region Events
146        public event StatusChangedEventHandler OnPluginStatusChanged;
147        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
148        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
149        #endregion
150
151        public ISettings Settings
152        {
153            get { return this.settings; }
154            set { this.settings = (DESSettings)value; }
155        }
156
157        public UserControl Presentation
158        {
159            get { return null; }
160        }
161
162        public UserControl QuickWatchPresentation
163        {
164            get { return null; }
165        }
166
167        public void Initialize()
168        {
169        }
170
171        public void Execute()
172        {
173            process(settings.Action);
174        }
175
176
177        public void Pause()
178        {
179
180        }
181
182        public void Stop()
183        {
184            this.stop = true;
185        }
186
187        public void Dispose()
188        {
189            try
190            {
191                stop = false;
192                inputKey = null;
193                inputIV = null;
194
195                inputStream = null;
196                outputStream = null;
197
198                foreach (CryptoolStream stream in listCryptoolStreamsOut)
199                {
200                    stream.Close();
201                }
202                listCryptoolStreamsOut.Clear();
203
204                if (p_crypto_stream != null)
205                {
206                    p_crypto_stream.Flush();
207                    p_crypto_stream.Close();
208                    p_crypto_stream = null;
209                }
210            }
211            catch (Exception ex)
212            {
213                GuiLogMessage(ex.Message, NotificationLevel.Error);
214            }
215            this.stop = false;
216        }
217
218       
219
220        public void PostExecution()
221        {
222            Dispose();
223        }
224
225        public void PreExecution()
226        {
227            Dispose();
228        }
229
230        #endregion
231
232        #region INotifyPropertyChanged Members
233
234        public event PropertyChangedEventHandler PropertyChanged;
235
236        public void OnPropertyChanged(string name)
237        {
238            if (PropertyChanged != null)
239            {
240                PropertyChanged(this, new PropertyChangedEventArgs(name));
241            }
242        }
243
244        #endregion
245
246           
247
248        #region Public DES specific members
249
250        public bool isStopped()
251        {
252
253            return this.stop;
254        }
255
256        #endregion
257
258
259        #region Private methods
260
261        private void ConfigureAlg(SymmetricAlgorithm alg)
262        {
263            //check for a valid key
264            if (this.inputKey == null)
265            {
266                //create a trivial key
267                inputKey = new byte[8];
268                // write a warning to the ouside word
269                GuiLogMessage("ERROR: No key provided. Using 0x000..00!", NotificationLevel.Error);
270            }
271            alg.Key = this.inputKey;
272
273            //check for a valid IV
274            if (this.inputIV == null)
275            {
276                //create a trivial key
277                inputIV = new byte[alg.BlockSize / 8];
278                GuiLogMessage("NOTE: No IV provided. Using 0x000..00!", NotificationLevel.Info);
279            }
280            alg.IV = this.inputIV;
281            switch (settings.Mode)
282            { //0="ECB"=default, 1="CBC", 2="CFB", 3="OFB"
283                case 1: alg.Mode = CipherMode.CBC; break;
284                case 2: alg.Mode = CipherMode.CFB; break;
285                case 3: alg.Mode = CipherMode.OFB; break;
286                default: alg.Mode = CipherMode.ECB; break;
287            }
288            switch (settings.Padding)
289            { //0="Zeros"=default, 1="None", 2="PKCS7"
290                case 1: alg.Padding = PaddingMode.None; break;
291                case 2: alg.Padding = PaddingMode.PKCS7; break;
292                case 3: alg.Padding = PaddingMode.ANSIX923; break;
293                case 4: alg.Padding = PaddingMode.ISO10126; break;
294                default: alg.Padding = PaddingMode.Zeros; break;
295            }
296        }
297
298        private void checkForInputStream()
299        {
300            if (settings.Action == 0 && (inputStream == null || (inputStream != null && inputStream.Length == 0)))
301            {
302                //create some input
303                String dummystring = "Dummy string - no input provided - \"Hello DES World\" - dummy string - no input provided!";
304                this.inputStream = new CryptoolStream();
305                this.inputStream.OpenRead(Encoding.Default.GetBytes(dummystring.ToCharArray()));
306                // write a warning to the ouside word
307                GuiLogMessage("WARNING - No input provided. Using dummy data. (" + dummystring + ")", NotificationLevel.Warning);
308            }
309        }
310
311        private void process(int action)
312        {
313            //Encrypt/Decrypt Stream
314            try
315            {
316                checkForInputStream();
317                if (inputStream == null || (inputStream != null && inputStream.Length == 0))
318                {
319                    GuiLogMessage("No input given. Not using dummy data in decrypt mode. Aborting now.", NotificationLevel.Error);
320                    return;
321                }
322
323                if (this.inputStream.CanSeek) this.inputStream.Position = 0;
324                SymmetricAlgorithm p_alg = new DESCryptoServiceProvider();
325
326                ConfigureAlg(p_alg);
327
328                ICryptoTransform p_encryptor = null;
329                switch (action)
330                {
331                    case 0:
332                        p_encryptor = p_alg.CreateEncryptor();
333                        break;
334                    case 1:
335                        p_encryptor = p_alg.CreateDecryptor();
336                        break;
337                }
338
339                outputStream = new CryptoolStream();
340                listCryptoolStreamsOut.Add(outputStream);
341                outputStream.OpenWrite();
342                p_crypto_stream = new CryptoStream((Stream)inputStream, p_encryptor, CryptoStreamMode.Read);
343                byte[] buffer = new byte[p_alg.BlockSize / 8];
344                int bytesRead;
345                int position = 0;
346                GuiLogMessage("Starting encryption [Keysize=" + p_alg.KeySize.ToString() + " Bits, Blocksize=" + p_alg.BlockSize.ToString() + " Bits]", NotificationLevel.Info);
347                DateTime startTime = DateTime.Now;
348                while ((bytesRead = p_crypto_stream.Read(buffer, 0, buffer.Length)) > 0 && !stop)
349                {
350                    outputStream.Write(buffer, 0, bytesRead);
351
352                    if ((int)(inputStream.Position * 100 / inputStream.Length) > position)
353                    {
354                        position = (int)(inputStream.Position * 100 / inputStream.Length);
355                        ProgressChanged(inputStream.Position, inputStream.Length);
356                    }
357                }
358
359                p_crypto_stream.Flush();
360                DateTime stopTime = DateTime.Now;
361                TimeSpan duration = stopTime - startTime;
362                if (!stop)
363                {
364                    GuiLogMessage("Encryption complete! (in: " + inputStream.Length.ToString() + " bytes, out: " + outputStream.Length.ToString() + " bytes)", NotificationLevel.Info);
365                    GuiLogMessage("Wrote data to file: " + outputStream.FileName, NotificationLevel.Info);
366                    GuiLogMessage("Time used: " + duration.ToString(), NotificationLevel.Debug);
367                    outputStream.Close();
368                    OnPropertyChanged("OutputStream");
369                }
370                if (stop)
371                {
372                    outputStream.Close();
373                    GuiLogMessage("Aborted!", NotificationLevel.Info);
374                }
375                ProgressChanged(1, 1);
376
377            }
378            catch (CryptographicException cryptographicException)
379            {
380                p_crypto_stream = null;
381                GuiLogMessage(cryptographicException.Message, NotificationLevel.Error);
382            }
383            catch (Exception exception)
384            {
385                GuiLogMessage(exception.Message, NotificationLevel.Error);
386            }
387            finally
388            {
389                ProgressChanged(1, 1);
390            }
391        }
392
393        private void GuiLogMessage(string message, NotificationLevel logLevel)
394        {
395            if (OnGuiLogNotificationOccured != null)
396            {
397                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, logLevel));
398            }
399        }
400
401
402        private void ProgressChanged(double value, double max)
403        {
404            if (OnPluginProgressChanged != null)
405            {
406                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
407            }
408        }
409
410        #endregion
411
412    }
413
414   
415    #region DESControl : IControlCubeAttack
416
417    public class CubeAttackControl : IControlCubeAttack
418    {
419        public event IControlStatusChangedEventHandler OnStatusChanged;
420        private DES plugin;
421
422        public CubeAttackControl(DES Plugin)
423        {
424            this.plugin = Plugin;
425        }
426
427        #region IControlEncryption Members
428
429        public int GenerateBlackboxOutputBit(object IV, object key, object length)
430        {
431            // public bits := plaintext
432            // secret bits := key
433            SymmetricAlgorithm p_alg = new DESCryptoServiceProvider();
434            string secretBits = string.Empty;
435            string publicBits = string.Empty;
436
437            // save public and secret bits as string
438            int[] temp = key as int[];
439            for (int i = 0; i < temp.Length; i++)
440                secretBits += temp[i];
441            temp = IV as int[];
442            for (int i = 0; i < temp.Length; i++)
443                publicBits += temp[i];
444
445            // convert secret bits to byte array
446            int[] arrInt = new int[8];
447            for (int i = 0; i < 8; i++)
448            {
449                for (int j = 0; j < 8; j++)
450                {
451                    if (secretBits[(8 * i) + j] == '1')
452                        arrInt[i] += (int)Math.Pow(2, 7 - j);
453                }
454            }
455            byte[] keyByte = new byte[8];
456            for (int i = 0; i < arrInt.Length; i++)
457                keyByte[i] = (byte)arrInt[i];
458
459            // convert public bits to byte array
460            arrInt = new int[8];
461            for (int i = 0; i < 8; i++)
462            {
463                for (int j = 0; j < 8; j++)
464                {
465                    if (publicBits[(8 * i) + j] == '1')
466                        arrInt[i] += (int)Math.Pow(2, 7 - j);
467                }
468            }
469            byte[] publicByte = new byte[8];
470            for (int i = 0; i < arrInt.Length; i++)
471                publicByte[i] = (byte)arrInt[i];
472
473            ICryptoTransform p_encryptor;
474            p_alg.IV = new byte[8];
475            p_alg.Padding = PaddingMode.Zeros;
476            try
477            {
478                p_alg.Key = keyByte;
479            }
480            catch
481            {
482                //dirty hack to allow weak keys:
483                FieldInfo field = p_alg.GetType().GetField("KeyValue", BindingFlags.NonPublic | BindingFlags.Instance);
484                field.SetValue(p_alg, keyByte);
485            }
486            try
487            {
488                p_encryptor = p_alg.CreateEncryptor();
489            }
490            catch
491            {
492                //dirty hack to allow weak keys:
493                MethodInfo mi = p_alg.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
494                object[] Par = { p_alg.Key, p_alg.Mode, p_alg.IV, p_alg.FeedbackSize, 0 };
495                p_encryptor = mi.Invoke(p_alg, Par) as ICryptoTransform;
496            }
497           
498            Stream inputPublic = new MemoryStream(publicByte);
499            // starting encryption
500            CryptoStream p_crypto_stream = new CryptoStream(inputPublic, p_encryptor, CryptoStreamMode.Read);
501            byte[] buffer = new byte[p_alg.BlockSize / 8];
502            p_crypto_stream.Read(buffer, 0, buffer.Length);
503               
504            // convert encrypted block to binary string
505            string strBytes = string.Empty;
506            for (int i = 0; i < buffer.Length; i++)
507            {
508                for (int j = 7; j >= 0; j--)
509                    strBytes += (buffer[i] & 1 << j) > 0 ? 1 : 0;
510            }
511            p_crypto_stream.Flush();
512
513            // return single output bit
514            return Int32.Parse(strBytes.Substring((int)length-1, 1));
515        }
516        #endregion
517    }
518
519    #endregion
520
521
522    #region DESControl : IControlEncryption
523    public class DESControl : IControlEncryption
524    {
525        public event KeyPatternChanged keyPatternChanged;
526        public event IControlStatusChangedEventHandler OnStatusChanged;
527
528       
529        private DES plugin;
530
531        public DESControl(DES Plugin)
532        {
533            this.plugin = Plugin;
534
535            // Change the padding mode to zeroes, since we want to do bruteforcing..
536            ((DESSettings)plugin.Settings).Padding = 0;
537        }
538
539       
540
541        public byte[] Encrypt(byte[] key, int blocksize)
542        {
543            /// not implemented, currently not needed
544            throw new NotImplementedException();
545        }
546
547        public byte[] Decrypt(byte[] ciphertext, byte[] key)
548        {
549            return Decrypt(ciphertext, key, ciphertext.Length);
550        }
551
552        // TODO: add override with iv, mode, blocksize
553        public byte[] Decrypt(byte[] ciphertext, byte[] key, int bytesToUse)
554        {
555            CryptoStream crypto_stream = null;
556            int size = bytesToUse > ciphertext.Length ? ciphertext.Length : bytesToUse;
557
558            byte[] output = new byte[size];
559           
560            // always recreating this instance is thread-safe, but may cost us some performance
561            SymmetricAlgorithm des_algorithm  = new DESCryptoServiceProvider();
562
563            switch (((DESSettings)plugin.Settings).Mode)
564            { //0="ECB"=default, 1="CBC", 2="CFB", 3="OFB"
565                case 1: des_algorithm.Mode = CipherMode.CBC; break;
566                case 2: des_algorithm.Mode = CipherMode.CFB; break;
567                case 3: des_algorithm.Mode = CipherMode.OFB; break;
568                default: des_algorithm.Mode = CipherMode.ECB; break;
569            }
570
571            // Padding for DES must always be set to zeroes
572            // other padding types lead to error while decrypting
573            // padding type of none leads to error if size does not match exactly a multiple of 8 Byte
574            des_algorithm.Padding = PaddingMode.Zeros;
575
576            // TODO: this must be passed via the interface
577            des_algorithm.IV = new byte[des_algorithm.BlockSize / 8]; // IV of 0x00..00
578
579            try
580            {
581                des_algorithm.Key = key;
582            }
583            catch
584            {
585                //dirty hack to allow weak keys:
586                FieldInfo field = des_algorithm.GetType().GetField("KeyValue", BindingFlags.NonPublic | BindingFlags.Instance);
587                //Console.WriteLine(des_algorithm.GetType());
588                field.SetValue(des_algorithm, key);
589            }
590
591            ICryptoTransform p_decryptor;
592            try
593            {
594                p_decryptor = des_algorithm.CreateDecryptor();
595            }
596            catch
597            {
598                //dirty hack to allow weak keys:
599                MethodInfo mi = des_algorithm.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
600                object[] Par = { des_algorithm.Key, des_algorithm.Mode, des_algorithm.IV, des_algorithm.FeedbackSize, 0 };
601                p_decryptor = mi.Invoke(des_algorithm, Par) as ICryptoTransform;
602            }
603
604            crypto_stream = new CryptoStream(new MemoryStream(ciphertext,0,size), p_decryptor, CryptoStreamMode.Read);
605
606            int read, readOverall = 0;
607            do
608            {
609                read = crypto_stream.Read(output, readOverall, output.Length - readOverall);
610                readOverall += read;
611            } while (read > 0 && readOverall < output.Length);
612
613            return output;
614        }
615
616        public string getKeyPattern()
617        {
618            return "[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-"
619                +"[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]-[0-9A-F][0-9A-F]";
620        }
621
622        public byte[] getKeyFromString(string key, ref int[] arrayPointers, ref int[] arraySuccessors, ref int[] arrayUppers)
623        {
624            byte[] bkey = new byte[8];
625            int counter = 0;
626            bool allocated = false;
627
628            for (int i = 0; i <= 7; i++)
629            {
630                string substr = key.Substring(i * 3, 2);
631
632                if (!allocated && (substr[0] == '*' || substr[1] == '*'))
633                {
634                    arrayPointers = new int[8];
635                    for (int j = 0; j < 8; j++)
636                        arrayPointers[j] = -1;
637                    arraySuccessors = new int[8];
638                    arrayUppers = new int[8];
639                    allocated = true;
640                }
641
642                if (substr[0] != '*' && substr[1] != '*')
643                    bkey[i] = Convert.ToByte(substr, 16);
644                else if (substr[0] == '*' && substr[1] == '*')
645                {
646                    bkey[i] = 0;
647                    arrayPointers[counter] = i;
648                    arraySuccessors[counter] = 1;
649                    arrayUppers[counter] = 255;
650                    counter++;
651                }
652                else if (substr[0] != '*' && substr[1] == '*')
653                {
654                    bkey[i] = Convert.ToByte(substr[0] + "0", 16);
655                    arrayPointers[counter] = i;
656                    arraySuccessors[counter] = 1;
657                    arrayUppers[counter] = Convert.ToByte(substr[0] + "F", 16);
658                    counter++;
659                }
660                else if (substr[0] == '*' && substr[1] != '*')
661                {
662                    bkey[i] = Convert.ToByte("0" + substr[1], 16);
663                    arrayPointers[counter] = i;
664                    arraySuccessors[counter] = 16;
665                    arrayUppers[counter] = Convert.ToByte("F" + substr[1], 16);
666                    counter++;
667                }
668            }
669            return bkey;
670        }
671
672        public IControlEncryption clone()
673        {
674            DESControl des = new DESControl(plugin);
675            return des;
676        }
677
678        public void Dispose()
679        {
680           
681        }
682
683        public void changeSettings(string setting, object value)
684        {
685            throw new NotImplementedException();
686        }
687
688    }
689    #endregion
690}
Note: See TracBrowser for help on using the repository browser.