source: trunk/CrypPlugins/RSA/RSAKeyGenerator.cs @ 1890

Last change on this file since 1890 was 1890, checked in by Sven Rech, 11 years ago

fixed rsa keygen bug

File size: 14.9 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*/
16
17using System;
18using System.Collections.Generic;
19using System.Linq;
20using System.Text;
21using Cryptool.PluginBase.Cryptography;
22using Cryptool.PluginBase.Miscellaneous;
23using Cryptool.PluginBase;
24using System.ComponentModel;
25using System.Security.Cryptography;
26using System.Security.Cryptography.X509Certificates;
27using System.Numerics;
28using System.Diagnostics;
29
30namespace Cryptool.Plugins.RSA
31{
32    [Author("Dennis Nolte, Raoul Falk, Sven Rech, Nils Kopal", "", "Uni Duisburg-Essen", "http://www.uni-due.de")]
33    [PluginInfo(true, "RSAKeyGenerator", "RSA Key Generator", "RSA/DetailedDescription/Description.xaml", "RSA/iconkey.png")]
34    [EncryptionType(EncryptionType.Asymmetric)]
35    ///<summary>
36    /// This plugin is a generator plugin which helps the user to generate pairs of private/public keys
37    /// for the RSA algorithm
38    ///
39    /// there are several modes:
40    ///
41    /// 1. manual
42    ///     in this mode the p and q or the n and e and d are given by the user, the d also may be generated
43    ///     
44    /// 2. generated
45    ///     in this mode all will be generated by microsoft classes
46    ///     
47    /// 3. certificate
48    ///     in this mode a x509 certificate will be loaded (the user can give a password for loading)
49    /// </summary>   
50    class RSAKeyGenerator : IEncryption
51    {
52        #region private members
53
54        private BigInteger n;       
55        private BigInteger e;
56        private BigInteger d;
57        private RSAKeyGeneratorSettings settings = new RSAKeyGeneratorSettings();
58
59        #endregion
60       
61        #region events
62
63        public event Cryptool.PluginBase.StatusChangedEventHandler OnPluginStatusChanged;
64        public event Cryptool.PluginBase.GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
65        public event Cryptool.PluginBase.PluginProgressChangedEventHandler OnPluginProgressChanged;
66        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
67
68        #endregion
69
70        #region public
71
72        /// <summary>
73        /// Sets the N of the public/private key
74        /// </summary>
75        [PropertyInfo(Direction.OutputData, "N", "N", "", DisplayLevel.Beginner)]
76        public BigInteger N
77        {
78            get
79            {
80                return n;
81            }
82            set
83            {
84                this.n = value;
85                OnPropertyChanged("N");
86            }
87        }
88
89        /// <summary>
90        /// Sets the E of the public key
91        /// </summary>
92        [PropertyInfo(Direction.OutputData, "E", "public exponent", "", DisplayLevel.Beginner)]
93        public BigInteger E
94        {
95            get
96            {
97                return e;
98            }
99            set
100            {
101                this.e = value;
102                OnPropertyChanged("E");
103            }
104        }
105
106        /// <summary>
107        /// Sets the D of the private key
108        /// </summary>
109        [PropertyInfo(Direction.OutputData, "D", "private exponent", "", DisplayLevel.Beginner)]
110        public BigInteger D
111        {
112            get
113            {
114                return d;
115            }
116            set
117            {
118                this.d = value;
119                OnPropertyChanged("D");
120            }
121        }
122
123        /// <summary>
124        /// Getter/Setter for the settings of this plugin
125        /// </summary>
126        public ISettings Settings
127        {
128            get { return this.settings; }
129            set { this.settings = (RSAKeyGeneratorSettings)value; }
130        }
131
132        /// <summary>
133        /// Get the presentation of this plugin
134        /// </summary>
135        public System.Windows.Controls.UserControl Presentation
136        {
137            get { return null; }
138        }
139
140        /// <summary>
141        /// Get the quickwatchpresentation of this plugin
142        /// </summary>
143        public System.Windows.Controls.UserControl QuickWatchPresentation
144        {
145            get { return null; }
146        }
147
148        /// <summary>
149        /// This method is called by the environment before execution
150        /// </summary>
151        public void PreExecution()
152        {
153
154        }
155
156        /// <summary>
157        /// Called by the environment to start generating of public/private keys
158        /// </summary>
159        public void Execute()
160        {
161            BigInteger p;
162            BigInteger q;
163            BigInteger n;
164            BigInteger e;
165            BigInteger d;
166
167            ProgressChanged(0.5, 1.0);
168            switch (settings.Source)
169            {
170                // manual
171                case 0:
172                    try
173                    {
174                        p = BigIntegerHelper.ParseExpression(settings.P);
175                        q = BigIntegerHelper.ParseExpression(settings.Q);
176                        e = BigIntegerHelper.ParseExpression(settings.E);
177
178                        if (!BigIntegerHelper.IsProbablePrime(p))
179                        {
180                            GuiLogMessage(p.ToString() + " is not prime!", NotificationLevel.Error);
181                            return;
182                        }
183                        if (!BigIntegerHelper.IsProbablePrime(q))
184                        {
185                            GuiLogMessage(q.ToString() + " is not prime!", NotificationLevel.Error);
186                            return;
187                        }
188                        if (p == q)
189                        {
190                            GuiLogMessage("The primes P and Q can not be equal!", NotificationLevel.Error);
191                            return;
192                        }
193                    }
194                    catch (Exception ex)
195                    {
196                        GuiLogMessage("Invalid Big Number input: " + ex.Message, NotificationLevel.Error);
197                        return;
198                    }
199
200                    try
201                    {
202                        D = BigIntegerHelper.ModInverse(e, (p - 1) * (q - 1));
203                    }
204                    catch (Exception)
205                    {
206                        GuiLogMessage("RSAKeyGenerator Error: E (" + e + ") can not be inverted.", NotificationLevel.Error);
207                        return;
208                    }
209                    try
210                    {                       
211                        N = p * q;
212                        E = e;                       
213                    }
214                    catch (Exception ex)
215                    {
216                        GuiLogMessage("Big Number fail: " + ex.Message, NotificationLevel.Error);
217                        return;
218                    }
219                    break;
220
221                case 1:
222                    try
223                    {
224                        n = BigIntegerHelper.ParseExpression(settings.N);
225                        d = BigIntegerHelper.ParseExpression(settings.D);
226                        e = BigIntegerHelper.ParseExpression(settings.E);
227                    }
228                    catch (Exception ex)
229                    {
230                        GuiLogMessage("Invalid Big Number input: " + ex.Message, NotificationLevel.Error);
231                        return;
232                    }
233                   
234                    try
235                    {
236                        N = n;
237                        E = e;
238                        D = d;
239                    }
240                    catch (Exception ex)
241                    {
242                        GuiLogMessage("Big Number fail: " + ex.Message, NotificationLevel.Error);
243                        return;
244                    }
245                    break;
246
247                //random generated
248                case 2:
249                    try
250                    {
251                        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
252                        RSAParameters rsaParameters = rsa.ExportParameters(true);
253                        p = BigIntegerHelper.FromPositiveReversedByteArray(rsaParameters.P);
254                        q = BigIntegerHelper.FromPositiveReversedByteArray(rsaParameters.Q);
255                        n = BigIntegerHelper.FromPositiveReversedByteArray(rsaParameters.Modulus);
256                        Debug.Assert(BigIntegerHelper.IsProbablePrime(p));
257                        Debug.Assert(BigIntegerHelper.IsProbablePrime(q));
258                        Debug.Assert((p * q) == n);
259                        e = BigIntegerHelper.FromPositiveReversedByteArray(rsaParameters.Exponent);
260                        d = BigIntegerHelper.FromPositiveReversedByteArray(rsaParameters.D);
261                        Debug.Assert((e * d) % ((p - 1) * (q - 1)) == 1);
262                    }
263                    catch (Exception ex)
264                    {
265                        GuiLogMessage(ex.Message, NotificationLevel.Error);
266                        return;
267                    }
268
269                    N = n;
270                    E = e;
271                    D = d;
272                    break;
273               
274                //using x509 certificate
275                case 3:
276                    try
277                    {
278
279                        X509Certificate2 cert;
280                        RSAParameters par;
281
282                        if (this.settings.Password != "")
283                        {
284                            GuiLogMessage("Password entered. Try getting public and private key", NotificationLevel.Info);
285                            cert = new X509Certificate2(settings.CertificateFile, settings.Password, X509KeyStorageFlags.Exportable);
286                            if (cert == null || cert.PrivateKey == null)
287                                throw new Exception("Private Key of X509Certificate could not be fetched");
288                            RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PrivateKey;                           
289                            par = provider.ExportParameters(true);                           
290                           
291                        }
292                        else 
293                        {
294                            GuiLogMessage("No Password entered. Try loading public key only", NotificationLevel.Info);
295                            cert = new X509Certificate2(settings.CertificateFile);
296                            if (cert == null || cert.PublicKey == null || cert.PublicKey.Key == null)
297                                throw new Exception("Private Key of X509Certificate could not be fetched");
298                            RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PublicKey.Key;
299                            par = provider.ExportParameters(false);
300                        }
301
302                        try
303                        {
304                            N = new BigInteger(par.Modulus);
305                        }
306                        catch (Exception ex)
307                        {
308                            GuiLogMessage("Could not get N from certificate: " + ex.Message, NotificationLevel.Warning);
309                        }
310
311                        try
312                        {
313                            E = new BigInteger(par.Exponent);
314                        }
315                        catch (Exception ex)
316                        {
317                            GuiLogMessage("Could not get E from certificate: " + ex.Message, NotificationLevel.Warning);
318                        }
319
320                        try
321                        {
322                            if (this.settings.Password != "")
323                                D = new BigInteger(par.D);
324                            else
325                                D = 0;
326                        }
327                        catch (Exception ex)
328                        {
329                            GuiLogMessage("Could not get D from certificate: " + ex.Message, NotificationLevel.Warning);
330                        }
331
332                    }
333                    catch (Exception ex)
334                    {
335                        GuiLogMessage("Could not load the selected certificate: " + ex.Message, NotificationLevel.Error);
336                    }
337                    break;
338            }
339            ProgressChanged(1.0, 1.0);
340        }
341
342        /// <summary>
343        /// This method is called by the environment after execution
344        /// </summary>
345        public void PostExecution()
346        {
347        }
348
349        /// <summary>
350        /// This method is called by the environment to pause this plugin
351        /// </summary>
352        public void Pause()
353        {
354
355        }
356
357        /// <summary>
358        /// This method is called by the environment to stop execution
359        /// </summary>
360        public void Stop()
361        {
362        }
363
364        /// <summary>
365        /// This method is called by the environment to initialise the plugin
366        /// </summary>
367        public void Initialize()
368        {
369            settings.UpdateTaskPaneVisibility();
370        }
371
372        /// <summary>
373        /// This method is called by the environment to dispose
374        /// </summary>
375        public void Dispose()
376        {
377        }
378       
379        #endregion
380
381        #region private
382
383        /// <summary>
384        /// Changes the progress of this plugin
385        /// </summary>
386        private void ProgressChanged(double value, double max)
387        {
388            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
389        }
390
391        /// <summary>
392        /// Logs a message to cryptool
393        /// </summary>
394        private void GuiLogMessage(string p, NotificationLevel notificationLevel)
395        {
396            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(p, this, notificationLevel));
397        }
398
399        /// <summary>
400        /// The property name changed
401        /// </summary>
402        /// <param name="name">name</param>
403        public void OnPropertyChanged(string name)
404        {
405            EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
406        }
407
408        #endregion
409   
410    }//end RSAKeyGenerator
411
412}//end Cryptool.Plugins.RSA
Note: See TracBrowser for help on using the repository browser.