Permalink
Browse files

[asp.net] Normalization of cryptographic uses in asp.net.

Backport of commit a22389f
    Normalization of cryptographic uses in asp.net

    * System.Web.Configuration_2.0/MachineKeyRegistryStorage.cs:
    Remove key length check and generic key generation.

    * System.Web.Configuration_2.0/MachineKeySection.cs: Add support for 4.0
    ValidationAlgorithm and the use of custom algorithms (validation and
    decryption). Allow the use of any, valid, key length (based on the
    algorithm). Let each algorithm creates its own key (e.g. special needs,
    default length...)

    * System.Web.Configuration_2.0/MachineKeySectionUtils.cs: Remove key
    generation (from random) code and 192bits key length hack (won't work
    with custom algorithms). Add support for new (4.0) algorithms, including
    custom ones. Provide uniform/shared code to Encrypt/Decrypt, Sign/Verify
    and EncryptSign/VerifyDecrypt using MachineKeySection data.

    * System.Web.Configuration_2.0/MachineKeyValidation.cs: Add new (4.0)
    values.

    * System.Web.Configuration_2.0/MachineKeyValidationConverter.cs: Add
    support for new (4.0) algorithms.

    * System.Web.Handlers/AssemblyResourceLoader.cs: Use the new common
    cryptographic code and base64 the encrypted data.

    * System.Web.Security/FormsAuthentication.cs: Use the new common
    cryptographic code and base64 the signed and/or encrypted data.

    * System.Web.Security/MembershipHelper.cs: Use the new common
    cryptographic code - this should be 100% compatible with existing data.

    * System.Web.Security/RolePrincipal.cs: Use the new common cryptographic
    code.

    * System.Web.Security/SqliteMembershipProvider.cs: Adapt code for
    internal API change.
  • Loading branch information...
1 parent 3c24090 commit f5501ef47531aa48531532160dbdc133ce93551e @grendello grendello committed Nov 24, 2010
Showing with 1,703 additions and 769 deletions.
  1. +2 −0 mcs/class/System.Web/Assembly/AssemblyInfo.cs
  2. +126 −72 mcs/class/System.Web/System.Web.Configuration/MachineKeyConfig.cs
  3. +2 −55 mcs/class/System.Web/System.Web.Configuration/MachineKeyRegistryStorage.cs
  4. +8 −4 mcs/class/System.Web/System.Web.Configuration/MachineKeyValidation.cs
  5. +40 −0 mcs/class/System.Web/System.Web.Configuration_2.0/MachineKeyCompatibilityMode.cs
  6. +201 −9 mcs/class/System.Web/System.Web.Configuration_2.0/MachineKeySection.cs
  7. +347 −95 mcs/class/System.Web/System.Web.Configuration_2.0/MachineKeySectionUtils.cs
  8. +53 −17 mcs/class/System.Web/System.Web.Configuration_2.0/MachineKeyValidationConverter.cs
  9. +21 −57 mcs/class/System.Web/System.Web.Handlers/AssemblyResourceLoader.cs
  10. +19 −148 mcs/class/System.Web/System.Web.Security/FormsAuthentication.cs
  11. +11 −35 mcs/class/System.Web/System.Web.Security/MembershipProvider.cs
  12. +17 −76 mcs/class/System.Web/System.Web.Security/RolePrincipal.cs
  13. +14 −3 mcs/class/System.Web/System.Web.Security/SqlMembershipProvider.cs
  14. +1 −1 mcs/class/System.Web/System.Web.Security/SqliteMembershipProvider.cs
  15. +2 −21 mcs/class/System.Web/System.Web.SessionState/SessionId.cs
  16. +45 −9 mcs/class/System.Web/System.Web.UI/LosFormatter.cs
  17. +72 −86 mcs/class/System.Web/System.Web.UI/ObjectStateFormatter.cs
  18. +0 −69 mcs/class/System.Web/System.Web.UI/Page.cs
  19. +1 −0 mcs/class/System.Web/System.Web.dll.sources
  20. +2 −0 mcs/class/System.Web/System.Web_test.dll.sources
  21. +158 −0 mcs/class/System.Web/Test/System.Web.Configuration/MachineKeySectionTest.cs
  22. +310 −0 mcs/class/System.Web/Test/System.Web.Configuration/MachineKeySectionUtilsTest.cs
  23. +77 −7 mcs/class/System.Web/Test/System.Web.Configuration/MachineKeyValidationConverterTest.cs
  24. +10 −0 mcs/class/System.Web/Test/System.Web.Security/FormsAuthenticationTest.cs
  25. +2 −2 mcs/class/System.Web/Test/System.Web.Security/RolePrincipalTest.cs
  26. +146 −2 mcs/class/System.Web/Test/System.Web.UI/LosFormatterTest.cs
  27. +15 −1 mcs/class/System.Web/Test/System.Web.UI/ObjectStateFormatterTest.cs
  28. +1 −0 mcs/class/System.Web/net_4_0_System.Web.dll.sources
@@ -69,6 +69,8 @@
[assembly: InternalsVisibleTo ("System.Web.DynamicData, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo ("SystemWebTestShim, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
+[assembly: InternalsVisibleTo ("System.Web_test_net_2_0, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
+[assembly: InternalsVisibleTo ("System.Web_test_net_4_0, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
#endif
#endif
@@ -39,23 +39,40 @@ namespace System.Web.Configuration
{
class MachineKeyConfig
{
- byte [] validation_key;
- //bool isolate_validation;
- byte [] decryption_key;
- byte [] decryption_key_192bits;
- //bool isolate_decryption; // For us, this is always true by now.
+ byte[] decryption_key;
+ byte[] validation_key;
+ string decryption_key_name;
+ string validation_key_name;
+ SymmetricAlgorithm decryption_template;
+ KeyedHashAlgorithm validation_template;
MachineKeyValidation validation_type;
- static byte [] autogenerated;
- static byte [] autogenerated_decrypt;
+ internal static MachineKeyConfig Config {
+ get {
+ HttpContext context = HttpContext.Current;
+ if (context == null)
+ return null;
+
+ return context.GetConfig ("system.web/machineKey") as MachineKeyConfig;
+ }
+ }
- static MachineKeyConfig ()
- {
- autogenerated = new byte [64];
- RandomNumberGenerator rng = RandomNumberGenerator.Create ();
- rng.GetBytes (autogenerated);
- autogenerated_decrypt = new byte [64];
- rng.GetBytes (autogenerated_decrypt);
+ // not to be reused outside algorithm and key validation purpose
+ SymmetricAlgorithm DecryptionTemplate {
+ get {
+ if (decryption_template == null)
+ decryption_template = GetDecryptionAlgorithm ();
+ return decryption_template;
+ }
+ }
+
+ // not to be reused outside algorithm and key validation purpose
+ KeyedHashAlgorithm ValidationTemplate {
+ get {
+ if (validation_template == null)
+ validation_template = GetValidationAlgorithm ();
+ return validation_template;
+ }
}
internal MachineKeyConfig (object parent)
@@ -68,75 +85,45 @@ internal MachineKeyConfig (object parent)
}
}
- static byte ToHexValue (char c, bool high)
+ internal byte [] GetDecryptionKey ()
{
- byte v;
- if (c >= '0' && c <= '9')
- v = (byte) (c - '0');
- else if (c >= 'a' && c <= 'f')
- v = (byte) (c - 'a' + 10);
- else if (c >= 'A' && c <= 'F')
- v = (byte) (c - 'A' + 10);
- else
- throw new ArgumentException ("Invalid hex character");
-
- if (high)
- v <<= 4;
-
- return v;
- }
-
- internal static byte [] GetBytes (string key, int len)
- {
- byte [] result = new byte [len / 2];
- for (int i = 0; i < len; i += 2)
- result [i / 2] = (byte) (ToHexValue (key [i], true) + ToHexValue (key [i + 1], false));
-
- return result;
+ if (decryption_key == null)
+ SetDecryptionKey (decryption_key_name);
+ return decryption_key;
}
- static byte [] MakeKey (string key, bool decryption) //, out bool isolate)
+ internal void SetDecryptionKey (string key)
{
- if (key == null || key.StartsWith ("AutoGenerate")){
- //isolate = key.IndexOf ("IsolateApps") != 1;
-
- return (decryption) ? autogenerated_decrypt : autogenerated;
+ if ((key == null) || key.StartsWith ("AutoGenerate")) {
+ decryption_key = AutoGenerate (MachineKeyRegistryStorage.KeyType.Encryption);
+ } else {
+ try {
+ decryption_key = MachineKeySectionUtils.GetBytes (key, key.Length);
+ DecryptionTemplate.Key = decryption_key;
+ }
+ catch {
+ decryption_key = null;
+ throw new ArgumentException ("Invalid key length");
+ }
}
-
- //isolate = false;
-
- int len = key.Length;
- if (len < 40 || len > 128 || (len % 2) == 1)
- throw new ArgumentException ("Invalid key length");
-
- return GetBytes (key, len);
}
-
- internal void SetValidationKey (string n)
+
+ internal KeyedHashAlgorithm GetValidationAlgorithm ()
{
- validation_key = MakeKey (n, false); //, out isolate_validation);
- }
-
- internal byte [] ValidationKey {
- get { return validation_key; }
+ // code location to help with unit testing the code
+ return MachineKeySectionUtils.GetValidationAlgorithm (this.ValidationType);
}
- internal void SetDecryptionKey (string n)
+ internal SymmetricAlgorithm GetDecryptionAlgorithm ()
{
- decryption_key = MakeKey (n, true); //, out isolate_decryption);
- decryption_key_192bits = new byte [24];
- int count = 24;
- if (decryption_key.Length < 24)
- count = decryption_key.Length;
- Buffer.BlockCopy (decryption_key, 0, decryption_key_192bits, 0, count);
- }
-
- internal byte [] DecryptionKey {
- get { return decryption_key; }
- }
+ string name;
- internal byte [] DecryptionKey192Bits {
- get { return decryption_key_192bits; }
+ if (decryption_key_name == null || decryption_key_name.StartsWith ("AutoGenerate"))
+ name = "Auto";
+ else
+ name = decryption_key_name;
+
+ return MachineKeySectionUtils.GetDecryptionAlgorithm (name);
}
internal MachineKeyValidation ValidationType {
@@ -147,6 +134,73 @@ internal void SetDecryptionKey (string n)
validation_type = value;
}
}
+
+ internal byte [] GetValidationKey ()
+ {
+ if (validation_key == null)
+ SetValidationKey (validation_key_name);
+ return validation_key;
+ }
+
+ // key can be expended for HMAC - i.e. a small key, e.g. 32 bytes, is still accepted as valid
+ // the HMAC class already deals with keys larger than what it can use (digested to right size)
+ internal void SetValidationKey (string key)
+ {
+ validation_key_name = key;
+ if ((key == null) || key.StartsWith ("AutoGenerate")) {
+ validation_key = AutoGenerate (MachineKeyRegistryStorage.KeyType.Validation);
+ } else {
+ try {
+ validation_key = MachineKeySectionUtils.GetBytes (key, key.Length);
+ ValidationTemplate.Key = validation_key;
+ }
+ catch (CryptographicException) {
+ // second chance, use the key length that the HMAC really wants
+ try {
+ byte[] expanded_key = new byte [ValidationTemplate.Key.Length];
+ Array.Copy (validation_key, 0, expanded_key, 0, validation_key.Length);
+ ValidationTemplate.Key = expanded_key;
+ validation_key = expanded_key;
+ }
+ catch {
+ validation_key = null;
+ throw new ArgumentException ("Invalid key length");
+ }
+ }
+ }
+ }
+
+ byte[] AutoGenerate (MachineKeyRegistryStorage.KeyType type)
+ {
+ byte[] key = null;
+#if TARGET_J2EE
+ {
+#else
+ try {
+ key = MachineKeyRegistryStorage.Retrieve (type);
+
+ // ensure the stored key is usable with the selection algorithm
+ if (type == MachineKeyRegistryStorage.KeyType.Encryption)
+ DecryptionTemplate.Key = key;
+ else if (type == MachineKeyRegistryStorage.KeyType.Validation)
+ ValidationTemplate.Key = key;
+ } catch (Exception) {
+ key = null;
+ }
+#endif
+ // some algorithms have special needs for key (e.g. length, parity, weak keys...)
+ // so we better ask them to provide a default key (than to generate/use bad ones)
+ if (key == null) {
+ if (type == MachineKeyRegistryStorage.KeyType.Encryption)
+ key = DecryptionTemplate.Key;
+ else if (type == MachineKeyRegistryStorage.KeyType.Validation)
+ key = ValidationTemplate.Key;
+#if !TARGET_J2EE
+ MachineKeyRegistryStorage.Store (key, type);
+#endif
+ }
+ return key;
+ }
}
}
@@ -28,8 +28,6 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
-using System.Security.Cryptography;
using Microsoft.Win32;
namespace System.Web.Configuration
@@ -42,9 +40,6 @@ public enum KeyType
Encryption
};
- const int encryptionKeyLength = 64;
- const int validationKeyLength = 64;
-
static string keyEncryption;
static string keyValidation;
@@ -62,31 +57,16 @@ static MachineKeyRegistryStorage ()
}
public static byte[] Retrieve (KeyType kt)
- {
- byte[] ret = GetKey (kt);
- if (ret == null) {
- ret = Generate (kt);
- if (ret != null)
- Store (ret, kt);
- }
-
- return ret;
- }
-
- static byte[] GetKey (KeyType kt)
{
string key = null;
- int len;
switch (kt) {
case KeyType.Validation:
key = keyValidation;
- len = validationKeyLength;
break;
case KeyType.Encryption:
key = keyEncryption;
- len = validationKeyLength;
break;
default:
@@ -107,11 +87,7 @@ static byte[] GetKey (KeyType kt)
if (o == null || o.GetType () != typeof (byte[]))
return null;
- byte[] ret = (byte[])o;
- if (ret.Length != len)
- return null;
-
- return ret;
+ return (byte[]) o;
}
static RegistryKey OpenRegistryKey (string path, bool write)
@@ -134,23 +110,19 @@ static RegistryKey OpenRegistryKey (string path, bool write)
return ret;
}
- static void Store (byte[] buf, KeyType kt)
+ public static void Store (byte[] buf, KeyType kt)
{
if (buf == null)
return;
string key = null;
- int len;
-
switch (kt) {
case KeyType.Validation:
key = keyValidation;
- len = validationKeyLength;
break;
case KeyType.Encryption:
key = keyEncryption;
- len = validationKeyLength;
break;
default:
@@ -160,9 +132,6 @@ static void Store (byte[] buf, KeyType kt)
if (key == null)
return;
- if (buf.Length != len)
- throw new ArgumentException ("Key has invalid length");
-
try {
using (RegistryKey rk = OpenRegistryKey (key, true)) {
#if NET_2_0
@@ -180,27 +149,5 @@ static void Store (byte[] buf, KeyType kt)
throw new ApplicationException ("Failed to store encryption key in the registry.", ex);
}
}
-
- static byte[] Generate (KeyType kt)
- {
- RandomNumberGenerator rng = RandomNumberGenerator.Create ();
- byte[] ret = null;
-
- switch (kt) {
- case KeyType.Validation:
- ret = new byte [validationKeyLength];
- break;
-
- case KeyType.Encryption:
- ret = new byte [encryptionKeyLength];
- break;
-
- default:
- throw new ArgumentException ("Unknown key type.");
- }
-
- rng.GetBytes (ret);
- return ret;
- }
}
}
@@ -23,11 +23,9 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004, 2010 Novell, Inc (http://www.novell.com)
//
-using System.Resources;
-
namespace System.Web.Configuration
{
#if NET_2_0
@@ -40,7 +38,13 @@ enum MachineKeyValidation
MD5 = 0,
SHA1 = 1,
TripleDES = 2,
- AES = 3
+ AES = 3,
+#if NET_4_0
+ HMACSHA256 = 4,
+ HMACSHA384 = 5,
+ HMACSHA512 = 6,
+ Custom = 7
+#endif
}
}
Oops, something went wrong.

0 comments on commit f5501ef

Please sign in to comment.