New test.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / RSA.cs
1 //
2 // System.Security.Cryptography.RSA.cs
3 //
4 // Authors:
5 //      Dan Lewis (dihlewis@yahoo.co.uk)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // (C) 2002
9 // Portions (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
10 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Globalization;
33 using System.Runtime.InteropServices;
34 using System.Text;
35
36 using Mono.Xml;
37
38 namespace System.Security.Cryptography {
39
40 #if NET_2_0
41         [ComVisible (true)]
42 #endif
43         public abstract class RSA : AsymmetricAlgorithm {
44
45                 public static new RSA Create () 
46                 {
47                         return Create ("System.Security.Cryptography.RSA");
48                 }
49
50                 public static new RSA Create (string algName)
51                 {
52                         return (RSA) CryptoConfig.CreateFromName (algName);
53                 }
54
55 #if NET_2_0
56                 protected RSA ()
57 #else
58                 public RSA ()
59 #endif
60                 {
61                 }
62
63                 public abstract byte[] EncryptValue (byte[] rgb);
64
65                 public abstract byte[] DecryptValue (byte[] rgb);
66
67                 public abstract RSAParameters ExportParameters (bool include);
68
69                 public abstract void ImportParameters (RSAParameters parameters);
70
71                 internal void ZeroizePrivateKey (RSAParameters parameters)
72                 {
73                         if (parameters.P != null)
74                                 Array.Clear (parameters.P, 0, parameters.P.Length);
75                         if (parameters.Q != null)
76                                 Array.Clear (parameters.Q, 0, parameters.Q.Length);
77                         if (parameters.DP != null)
78                                 Array.Clear (parameters.DP, 0, parameters.DP.Length);
79                         if (parameters.DQ != null)
80                                 Array.Clear (parameters.DQ, 0, parameters.DQ.Length);
81                         if (parameters.InverseQ != null)
82                                 Array.Clear (parameters.InverseQ, 0, parameters.InverseQ.Length);
83                         if (parameters.D != null)
84                                 Array.Clear (parameters.D, 0, parameters.D.Length);
85                 }
86
87                 private byte[] GetNamedParam (SecurityElement se, string param) 
88                 {
89                         SecurityElement sep = se.SearchForChildByTag (param);
90                         if (sep == null)
91                                 return null;
92                         return Convert.FromBase64String (sep.Text);
93                 }
94
95                 public override void FromXmlString (string xmlString) 
96                 {
97                         if (xmlString == null)
98                                 throw new ArgumentNullException ("xmlString");
99
100                         RSAParameters rsaParams = new RSAParameters ();
101                         try {
102                                 SecurityParser sp = new SecurityParser ();
103                                 sp.LoadXml (xmlString);
104                                 SecurityElement se = sp.ToXml ();
105
106                                 rsaParams.P = GetNamedParam (se, "P");
107                                 rsaParams.Q = GetNamedParam (se, "Q");
108                                 rsaParams.D = GetNamedParam (se, "D");
109                                 rsaParams.DP = GetNamedParam (se, "DP");
110                                 rsaParams.DQ = GetNamedParam (se, "DQ");
111                                 rsaParams.InverseQ = GetNamedParam (se, "InverseQ");
112                                 rsaParams.Exponent = GetNamedParam (se, "Exponent");
113                                 rsaParams.Modulus = GetNamedParam (se, "Modulus");
114                                 ImportParameters (rsaParams);
115                         }
116                         catch (Exception e) {
117                                 ZeroizePrivateKey (rsaParams);
118                                 throw new CryptographicException (
119                                         Locale.GetText ("Couldn't decode XML"), e);
120                         }
121                         finally {
122                                 ZeroizePrivateKey (rsaParams);
123                         }
124                 }
125
126                 public override string ToXmlString (bool includePrivateParameters) 
127                 {
128                         StringBuilder sb = new StringBuilder ();
129                         RSAParameters rsaParams = ExportParameters (includePrivateParameters);
130                         try {
131                                 sb.Append ("<RSAKeyValue>");
132                                 
133                                 sb.Append ("<Modulus>");
134                                 sb.Append (Convert.ToBase64String (rsaParams.Modulus));
135                                 sb.Append ("</Modulus>");
136
137                                 sb.Append ("<Exponent>");
138                                 sb.Append (Convert.ToBase64String (rsaParams.Exponent));
139                                 sb.Append ("</Exponent>");
140
141                                 if (includePrivateParameters) {
142                                         // we want an ArgumentNullException is only the D is missing, but a
143                                         // CryptographicException if other parameters (CRT) are missings
144                                         if (rsaParams.D == null) {
145                                                 string msg = Locale.GetText ("Missing D parameter for the private key.");
146                                                 throw new ArgumentNullException (msg);
147                                         } else if ((rsaParams.P == null) || (rsaParams.Q == null) || (rsaParams.DP == null) ||
148                                                 (rsaParams.DQ == null) || (rsaParams.InverseQ == null)) {
149                                                 // note: we can import a private key, using FromXmlString,
150                                                 // without the CRT parameters but we export it using ToXmlString!
151                                                 string msg = Locale.GetText ("Missing some CRT parameters for the private key.");
152                                                 throw new CryptographicException (msg);
153                                         }
154
155                                         sb.Append ("<P>");
156                                         sb.Append (Convert.ToBase64String (rsaParams.P));
157                                         sb.Append ("</P>");
158
159                                         sb.Append ("<Q>");
160                                         sb.Append (Convert.ToBase64String (rsaParams.Q));
161                                         sb.Append ("</Q>");
162
163                                         sb.Append ("<DP>");
164                                         sb.Append (Convert.ToBase64String (rsaParams.DP));
165                                         sb.Append ("</DP>");
166
167                                         sb.Append ("<DQ>");
168                                         sb.Append (Convert.ToBase64String (rsaParams.DQ));
169                                         sb.Append ("</DQ>");
170
171                                         sb.Append ("<InverseQ>");
172                                         sb.Append (Convert.ToBase64String (rsaParams.InverseQ));
173                                         sb.Append ("</InverseQ>");
174
175                                         sb.Append ("<D>");
176                                         sb.Append (Convert.ToBase64String (rsaParams.D));
177                                         sb.Append ("</D>");
178                                 }
179                                 
180                                 sb.Append ("</RSAKeyValue>");
181                         }
182                         catch {
183                                 ZeroizePrivateKey (rsaParams);
184                                 throw;
185                         }
186                         
187                         return sb.ToString ();
188                 }
189         }
190 }