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

Last change on this file since 1193 was 1193, checked in by Sven Rech, 12 years ago

more speed for bruteforcing by using unsafe code in AES and DES (just temporary)

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