2 // System.Web.Configuration.MachineKeyRegistryStorage
5 // Marek Habersack <mhabersack@novell.com>
7 // (C) 2007 Novell, Inc
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Security.Cryptography;
33 using Microsoft.Win32;
35 namespace System.Web.Configuration
37 internal class MachineKeyRegistryStorage
45 const int encryptionKeyLength = 64;
46 const int validationKeyLength = 64;
48 static string keyEncryption;
49 static string keyValidation;
51 static MachineKeyRegistryStorage ()
53 string appName = AppDomain.CurrentDomain.SetupInformation.ApplicationName;
57 string hash = appName.GetHashCode ().ToString ("x");
58 keyEncryption = "software\\mono\\asp.net\\" + Environment.Version.ToString () +
59 "\\autogenkeys\\" + hash + "-" + ((int)KeyType.Encryption).ToString ();
60 keyValidation = "software\\mono\\asp.net\\" + Environment.Version.ToString () +
61 "\\autogenkeys\\" + hash + "-" + ((int)KeyType.Validation).ToString ();
64 public static byte[] Retrieve (KeyType kt)
66 byte[] ret = GetKey (kt);
76 static byte[] GetKey (KeyType kt)
82 case KeyType.Validation:
84 len = validationKeyLength;
87 case KeyType.Encryption:
89 len = validationKeyLength;
93 throw new ArgumentException ("Unknown key type.");
102 RegistryKey v = OpenRegistryKey (key, false);
103 o = v.GetValue ("AutoGenKey", null);
104 } catch (Exception) {
108 if (o == null || o.GetType () != typeof (byte[]))
110 byte[] ret = (byte[])o;
111 if (ret.Length != len)
117 static RegistryKey OpenRegistryKey (string path, bool write)
119 RegistryKey ret, tmp;
120 string[] keys = path.Split ('\\');
121 int klen = keys.Length;
123 ret = Registry.CurrentUser;
124 for (int i = 0; i < klen; i++) {
125 tmp = ret.OpenSubKey (keys [i], true);
129 tmp = ret.CreateSubKey (keys [i]);
137 static void Store (byte[] buf, KeyType kt)
146 case KeyType.Validation:
148 len = validationKeyLength;
151 case KeyType.Encryption:
153 len = validationKeyLength;
157 throw new ArgumentException ("Unknown key type.");
163 if (buf.Length != len)
164 throw new ArgumentException ("Key has invalid length");
167 using (RegistryKey rk = OpenRegistryKey (key, true)) {
169 rk.SetValue ("AutoGenKey", buf, RegistryValueKind.Binary);
170 rk.SetValue ("AutoGenKeyCreationTime", DateTime.Now.Ticks, RegistryValueKind.QWord);
171 rk.SetValue ("AutoGenKeyFormat", 2, RegistryValueKind.DWord);
173 rk.SetValue ("AutoGenKey", buf);
174 rk.SetValue ("AutoGenKeyCreationTime", DateTime.Now.Ticks);
175 rk.SetValue ("AutoGenKeyFormat", 2);
177 rk.Flush (); // we want it synchronous
179 } catch (Exception ex) {
180 throw new ApplicationException ("Failed to store encryption key in the registry.", ex);
184 static byte[] Generate (KeyType kt)
186 RandomNumberGenerator rng = RandomNumberGenerator.Create ();
190 case KeyType.Validation:
191 ret = new byte [validationKeyLength];
194 case KeyType.Encryption:
195 ret = new byte [encryptionKeyLength];
199 throw new ArgumentException ("Unknown key type.");