source: trunk/CrypPlugins/TripleDES/TripleDES.cs @ 1785

Last change on this file since 1785 was 419, checked in by Thomas Schmid, 12 years ago
  • merged IControl branch to trunk
  • added KeySearcher sample: KeySearcher-Sample
  • changed some plugins to work with new enumeration
  • new bins
File size: 13.2 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;
12
13
14
15namespace Cryptool.Plugins.Cryptography.Encryption
16{
17    [Author("Sebastian Przybylski", "sebastian@przybylski.org", "Uni-Siegen", "http://www.uni-siegen.de")]
18    [PluginInfo(false, "Triple DES", "Triple Data Encryption Standard", null,
19      "TripleDES/Images/icon.png", "TripleDES/Images/encrypt.png", "TripleDES/Images/decrypt.png")]
20    [EncryptionType(EncryptionType.SymmetricBlock)]
21    public class TripleDES : IEncryption
22    {
23        #region Private variables
24        private TripleDESSettings settings;
25        private CryptoolStream inputStream;
26        private CryptoolStream outputStream;
27        private byte[] inputKey;
28        private byte[] inputIV;
29        private CryptoStream p_crypto_stream;
30        private bool stop = false;
31        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
32        #endregion
33
34        public TripleDES()
35        {
36            this.settings = new TripleDESSettings();
37            this.settings.OnPluginStatusChanged += settings_OnPluginStatusChanged;
38        }
39
40        void settings_OnPluginStatusChanged(IPlugin sender, StatusEventArgs args)
41        {
42            if (OnPluginStatusChanged != null) OnPluginStatusChanged(this, args);
43        }
44
45        public ISettings Settings
46        {
47            get { return this.settings; }
48            set { this.settings = (TripleDESSettings)value; }
49        }
50
51        [PropertyInfo(Direction.InputData, "Input", "Data to be encrypted or decrypted", null, true, false, DisplayLevel.Beginner,QuickWatchFormat.Hex, null)]
52        public CryptoolStream InputStream
53        {
54            get
55            {
56                if (inputStream != null)
57                {
58                    CryptoolStream cs = new CryptoolStream();
59                    cs.OpenRead(inputStream.FileName);
60                    listCryptoolStreamsOut.Add(cs);
61                    return cs;
62                }
63                else return null;
64            }
65            set
66            {
67                this.inputStream = value;
68                if (value != null) listCryptoolStreamsOut.Add(value);
69                OnPropertyChanged("InputStream");
70            }
71        }
72
73        [PropertyInfo(Direction.InputData, "Key", "Must be 16 or 24 bytes.", null, true, false, DisplayLevel.Beginner,QuickWatchFormat.Hex, null)]
74        public byte[] InputKey
75        {
76            get { return this.inputKey; }
77            set
78            {
79                this.inputKey = value;
80                OnPropertyChanged("InputKey");
81            }
82        }
83
84        [PropertyInfo(Direction.InputData, "IV", "IV to be used in chaining modes, must be the same as the Blocksize in bytes (8 bytes).", null, true, false, DisplayLevel.Professional, QuickWatchFormat.Hex, null)]
85        public byte[] InputIV
86        {
87            get { return this.inputIV; }
88            set
89            {
90                this.inputIV = value;
91                OnPropertyChanged("InputIV");
92            }
93
94        }
95
96        [PropertyInfo(Direction.OutputData, "Output stream", "Encrypted or decrypted output data", null, true, false, DisplayLevel.Beginner,QuickWatchFormat.Hex, null)]
97        public CryptoolStream OutputStream
98        {
99            get
100            {
101                if (this.outputStream != null)
102                {
103                    CryptoolStream cs = new CryptoolStream();
104                    listCryptoolStreamsOut.Add(cs);
105                    cs.OpenRead(this.outputStream.FileName);
106                    return cs;
107                }
108                return null;
109            }
110            set
111            {
112                outputStream = value;
113                if (value != null) listCryptoolStreamsOut.Add(value);
114                OnPropertyChanged("OutputStream");
115            }
116        }
117
118        private void ConfigureAlg(SymmetricAlgorithm alg)
119        {
120            //check for a valid key
121            if (this.inputKey == null)
122            {
123                //create a trivial key
124                inputKey = new byte[16];
125                // write a warning to the ouside word
126                GuiLogMessage("WARNING - No key provided. Using 0x000..00!", NotificationLevel.Warning);
127            }
128            alg.Key = this.inputKey;
129
130            //check for a valid IV
131            if (this.inputIV == null)
132            {
133                //create a trivial key
134                inputIV = new byte[alg.BlockSize / 8];
135                GuiLogMessage("WARNING - No IV provided. Using 0x000..00!", NotificationLevel.Warning);
136            }
137            alg.IV = this.inputIV;
138            switch (settings.Mode)
139            { //0="ECB"=default, 1="CBC", 2="CFB", 3="OFB"
140                case 1: alg.Mode = CipherMode.CBC; break;
141                case 2: alg.Mode = CipherMode.CFB; break;
142                case 3: alg.Mode = CipherMode.OFB; break;
143                default: alg.Mode = CipherMode.ECB; break;
144            }
145            switch (settings.Padding)
146            { //0="Zeros"=default, 1="None", 2="PKCS7"
147                case 1: alg.Padding = PaddingMode.None; break;
148                case 2: alg.Padding = PaddingMode.PKCS7; break;
149                case 3: alg.Padding = PaddingMode.ANSIX923; break;
150                case 4: alg.Padding = PaddingMode.ISO10126; break;
151                default: alg.Padding = PaddingMode.Zeros; break;
152            }
153        }
154
155        private void checkForInputStream()
156        {
157            if (settings.Action == 0 && (inputStream == null || (inputStream != null && inputStream.Length == 0)))
158            {
159                //create some input
160                String dummystring = "Dummy string - no input provided - \"Hello TripleDES World\" - dummy string - no input provided!";
161                this.inputStream = new CryptoolStream();
162                this.inputStream.OpenRead(this.GetPluginInfoAttribute().Caption, Encoding.Default.GetBytes(dummystring.ToCharArray()));
163                // write a warning to the ouside word
164                GuiLogMessage("WARNING - No input provided. Using dummy data. (" + dummystring + ")", NotificationLevel.Warning);
165            }
166        }
167
168        public void Execute()
169        {
170            process(settings.Action);
171        }
172
173        private void process(int action)
174        {
175            //Encrypt/Decrypt Stream
176            try
177            {
178                checkForInputStream();
179                if (inputStream == null || (inputStream != null && inputStream.Length == 0))
180                {
181                    GuiLogMessage("No input given. Not using dummy data in decrypt mode. Aborting now.", NotificationLevel.Error);
182                    return;
183                }
184
185                if (this.inputStream.CanSeek) this.inputStream.Position = 0;
186                SymmetricAlgorithm p_alg = new TripleDESCryptoServiceProvider();
187
188                ConfigureAlg(p_alg);
189
190                ICryptoTransform p_encryptor = null;
191                switch (action)
192                {
193                    case 0:
194                        p_encryptor = p_alg.CreateEncryptor();
195                        break;
196                    case 1:
197                        p_encryptor = p_alg.CreateDecryptor();
198                        break;
199                }
200
201                outputStream = new CryptoolStream();
202                listCryptoolStreamsOut.Add(outputStream);
203                outputStream.OpenWrite(this.GetPluginInfoAttribute().Caption);
204                p_crypto_stream = new CryptoStream((Stream)inputStream, p_encryptor, CryptoStreamMode.Read);
205                byte[] buffer = new byte[p_alg.BlockSize / 8];
206                int bytesRead;
207                int position = 0;
208                GuiLogMessage("Starting encryption [Keysize=" + p_alg.KeySize.ToString() + " Bits, Blocksize=" + p_alg.BlockSize.ToString() + " Bits]", NotificationLevel.Info);
209                DateTime startTime = DateTime.Now;
210                while ((bytesRead = p_crypto_stream.Read(buffer, 0, buffer.Length)) > 0 && !stop)
211                {
212                    outputStream.Write(buffer, 0, bytesRead);
213
214                    if ((int)(inputStream.Position * 100 / inputStream.Length) > position)
215                    {
216                        position = (int)(inputStream.Position * 100 / inputStream.Length);
217                        ProgressChanged(inputStream.Position, inputStream.Length);
218                    }
219                }
220                p_crypto_stream.Flush();
221                // p_crypto_stream.Close();
222                outputStream.Close();
223                DateTime stopTime = DateTime.Now;
224                TimeSpan duration = stopTime - startTime;
225                // (outputStream as CryptoolStream).FinishWrite();
226                if (!stop)
227                {
228                    GuiLogMessage("Encryption complete! (in: " + inputStream.Length.ToString() + " bytes, out: " + outputStream.Length.ToString() + " bytes)", NotificationLevel.Info);
229                    GuiLogMessage("Wrote data to file: " + outputStream.FileName, NotificationLevel.Info);
230                    GuiLogMessage("Time used: " + duration.ToString(), NotificationLevel.Debug);
231                    OnPropertyChanged("OutputStream");
232                }
233                if (stop)
234                {
235                    GuiLogMessage("Aborted!", NotificationLevel.Info);
236                }
237            }
238            catch (CryptographicException cryptographicException)
239            {
240                // TODO: For an unknown reason p_crypto_stream can not be closed after exception.
241                // Trying so makes p_crypto_stream throw the same exception again. So in Dispose
242                // the error messages will be doubled.
243                // As a workaround we set p_crypto_stream to null here.
244                p_crypto_stream = null;
245                GuiLogMessage(cryptographicException.Message, NotificationLevel.Error);
246            }
247            catch (Exception exception)
248            {
249                GuiLogMessage(exception.Message, NotificationLevel.Error);
250            }
251            finally
252            {
253                ProgressChanged(1, 1);
254            }
255        }
256
257        public void Encrypt()
258        {
259            //Encrypt Stream
260            process(0);
261        }
262
263        public void Decrypt()
264        {
265            //Decrypt Stream
266            process(1);
267        }
268
269        #region IPlugin Member
270
271        public System.Windows.Controls.UserControl Presentation
272        {
273            get { return null; }
274        }
275
276        public UserControl QuickWatchPresentation
277        {
278            get { return null; }
279        }
280
281        public void Initialize()
282        {
283        }
284
285        public void Dispose()
286        {
287            try
288            {
289                stop = false;
290                inputKey = null;
291                inputIV = null;
292
293                foreach (CryptoolStream stream in listCryptoolStreamsOut)
294                {
295                    stream.Close();
296                }
297                listCryptoolStreamsOut.Clear();
298
299                if (p_crypto_stream != null)
300                {
301                    p_crypto_stream.Flush();
302                    p_crypto_stream.Clear();
303                    p_crypto_stream = null;
304                }
305            }
306            catch (Exception ex)
307            {
308                GuiLogMessage(ex.Message, NotificationLevel.Error);
309            }
310            this.stop = false;
311        }
312
313        public void Stop()
314        {
315            this.stop = true;
316        }
317
318        public void PostExecution()
319        {
320            Dispose();
321        }
322
323        public void PreExecution()
324        {
325            Dispose();
326        }
327
328        #endregion
329
330        #region INotifyPropertyChanged Members
331
332        public event PropertyChangedEventHandler PropertyChanged;
333
334        public void OnPropertyChanged(string name)
335        {
336            if (PropertyChanged != null)
337            {
338                PropertyChanged(this, new PropertyChangedEventArgs(name));
339            }
340        }
341
342        #endregion
343
344        #region IPlugin Members
345
346        public event StatusChangedEventHandler OnPluginStatusChanged;
347
348        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
349        private void GuiLogMessage(string message, NotificationLevel logLevel)
350        {
351            if (OnGuiLogNotificationOccured != null)
352            {
353                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, logLevel));
354            }
355        }
356
357        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
358        private void ProgressChanged(double value, double max)
359        {
360            if (OnPluginProgressChanged != null)
361            {
362                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
363            }
364        }
365
366        public void Pause()
367        {
368        }
369
370        #endregion
371    }
372}
Note: See TracBrowser for help on using the repository browser.