//
#if NET_2_0
+using System.ComponentModel;
using System.Configuration.Provider;
using System.Web.Configuration;
using System.Security.Cryptography;
{
public abstract class MembershipProvider : ProviderBase
{
+ static readonly object validatingPasswordEvent = new object ();
+
+ EventHandlerList events = new EventHandlerList ();
+ public event MembershipValidatePasswordEventHandler ValidatingPassword {
+ add { events.AddHandler (validatingPasswordEvent, value); }
+ remove { events.RemoveHandler (validatingPasswordEvent, value); }
+ }
+
protected MembershipProvider ()
{
}
protected virtual void OnValidatingPassword (ValidatePasswordEventArgs args)
{
- if (ValidatingPassword != null)
- ValidatingPassword (this, args);
+ MembershipValidatePasswordEventHandler eh = events [validatingPasswordEvent] as MembershipValidatePasswordEventHandler;
+ if (eh != null)
+ eh (this, args);
}
- protected virtual byte[] DecryptPassword (byte[] encodedPassword)
+ SymmetricAlgorithm GetAlg (out byte [] decryptionKey)
{
- throw new NotImplementedException ();
- }
+ MachineKeySection section = (MachineKeySection) WebConfigurationManager.GetSection ("system.web/machineKey");
- protected virtual byte[] EncryptPassword (byte[] password)
- {
- throw new NotImplementedException ();
- }
+ if (section.DecryptionKey.StartsWith ("AutoGenerate"))
+ throw new ProviderException ("You must explicitly specify a decryption key in the <machineKey> section when using encrypted passwords.");
+
+ string alg_type = section.Decryption;
+ if (alg_type == "Auto")
+ alg_type = "AES";
- public event MembershipValidatePasswordEventHandler ValidatingPassword;
+ SymmetricAlgorithm alg = null;
+ if (alg_type == "AES")
+ alg = Rijndael.Create ();
+ else if (alg_type == "3DES")
+ alg = TripleDES.Create ();
+ else
+ throw new ProviderException (String.Format ("Unsupported decryption attribute '{0}' in <machineKey> configuration section", alg_type));
+
+ decryptionKey = MachineKeySectionUtils.DecryptionKey192Bits (section);
+ return alg;
+ }
- internal string EncodePassword (string password, MembershipPasswordFormat passwordFormat, string salt)
+ internal const int SALT_BYTES = 16;
+ protected virtual byte [] DecryptPassword (byte [] encodedPassword)
{
- byte[] password_bytes;
- byte[] salt_bytes;
-
- switch (passwordFormat) {
- case MembershipPasswordFormat.Clear:
- return password;
- case MembershipPasswordFormat.Hashed:
- password_bytes = Encoding.Unicode.GetBytes (password);
- salt_bytes = Convert.FromBase64String (salt);
-
- byte[] hashBytes = new byte[salt_bytes.Length + password_bytes.Length];
-
- Buffer.BlockCopy (salt_bytes, 0, hashBytes, 0, salt_bytes.Length);
- Buffer.BlockCopy (password_bytes, 0, hashBytes, salt_bytes.Length, password_bytes.Length);
-
- MembershipSection section = (MembershipSection)WebConfigurationManager.GetSection ("system.web/membership");
- string alg_type = section.HashAlgorithmType;
- if (alg_type == "") {
- MachineKeySection keysection = (MachineKeySection)WebConfigurationManager.GetSection ("system.web/machineKey");
- alg_type = keysection.Validation.ToString ();
- }
- using (HashAlgorithm hash = HashAlgorithm.Create (alg_type)) {
- hash.TransformFinalBlock (hashBytes, 0, hashBytes.Length);
- return Convert.ToBase64String (hash.Hash);
- }
- case MembershipPasswordFormat.Encrypted:
- password_bytes = Encoding.Unicode.GetBytes (password);
- salt_bytes = Convert.FromBase64String (salt);
+ byte [] decryptionKey;
+
+ using (SymmetricAlgorithm alg = GetAlg (out decryptionKey)) {
+ alg.Key = decryptionKey;
- byte[] buf = new byte[password_bytes.Length + salt_bytes.Length];
+ using (ICryptoTransform decryptor = alg.CreateDecryptor ()) {
- Array.Copy (salt_bytes, 0, buf, 0, salt_bytes.Length);
- Array.Copy (password_bytes, 0, buf, salt_bytes.Length, password_bytes.Length);
+ byte [] buf = decryptor.TransformFinalBlock (encodedPassword, 0, encodedPassword.Length);
+ byte [] rv = new byte [buf.Length - SALT_BYTES];
- return Convert.ToBase64String (EncryptPassword (buf));
- default:
- /* not reached.. */
- return null;
+ Array.Copy (buf, 16, rv, 0, buf.Length - 16);
+ return rv;
+ }
}
}
- internal string DecodePassword (string password, MembershipPasswordFormat passwordFormat)
+ protected virtual byte[] EncryptPassword (byte[] password)
{
- switch (passwordFormat) {
- case MembershipPasswordFormat.Clear:
- return password;
- case MembershipPasswordFormat.Hashed:
- throw new ProviderException ("Hashed passwords cannot be decoded.");
- case MembershipPasswordFormat.Encrypted:
- return Encoding.Unicode.GetString (DecryptPassword (Convert.FromBase64String (password)));
- default:
- /* not reached.. */
- return null;
+ byte [] decryptionKey;
+ byte [] iv = new byte [SALT_BYTES];
+
+ Array.Copy (password, 0, iv, 0, Math.Min(password.Length, SALT_BYTES));
+
+ using (SymmetricAlgorithm alg = GetAlg (out decryptionKey)) {
+ using (ICryptoTransform encryptor = alg.CreateEncryptor (decryptionKey, iv)) {
+ return encryptor.TransformFinalBlock (password, 0, password.Length);
+ }
}
}
}
}
#endif
+