source: trunk/CrypPlugins/RC2/RC2.cs @ 1507

Last change on this file since 1507 was 1259, checked in by Matthäus Wander, 12 years ago

shortened license text to boilerplate notice in all source files

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