ASP.NET MembershipProvider - How exactly does it encrypt?

I need to understand the details of how MembershipProvider performs encryption:

  • What algorithm does he use?
  • Is there any base64 encoding preprocessing or post processing?
  • Anything else in addition to the standard algorithms that he uses?

Given a simple text-based password for encryption, please go through the exact steps that return the final encrypted password.

I think that seeing the source code will be a long way in answering my questions, but I could not find it on the Internet. I found this documentation that does not provide implementation details.

Thanks for any info!

+4
source share
3 answers

Below is the code you want / need ... it's a bit of a rabbit courtship, so to fully understand, I would recommend doing the following:

  • Install ReSharper
    [Optional] Install dotPeek
  • Enter the following code anywhere:
    var dummyMembershipProvider = new SqlMembershipProvider();
    dummyMembershipProvider.ChangePassword("userName", "oldPassword", "newPassword");
  • Ctrl + left click (go to definition) on ChangePassword
  • This will begin your journey through rabbit warren ... it should look something like this:
    SqlMembershipProvider.ChangePassword
    SqlMembershipProvider.EncodePassword
    MembershipProvider.EncryptPassword
    IMembershipAdapter.EncryptOrDecryptData
    MembershipAdapter.EncryptOrDecryptData
    MachineKeySection.EncryptOrDecryptData
  • Get ReSharper because you understand that you can no longer live without it.

Anyway, here is MachineKeySection.EncryptOrDecryptData:

 public sealed class MachineKeySection : ConfigurationSection { internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, bool useValidationSymAlgo, bool useLegacyMode, IVType ivType) { EnsureConfig(); if (useLegacyMode) useLegacyMode = _UsingCustomEncryption; // only use legacy mode for custom algorithms System.IO.MemoryStream ms = new System.IO.MemoryStream(); ICryptoTransform oDesEnc = GetCryptoTransform(fEncrypt, useValidationSymAlgo, useLegacyMode); CryptoStream cs = new CryptoStream(ms, oDesEnc, CryptoStreamMode.Write); // DevDiv Bugs 137864: Add Random or Hashed IV to beginning of data to be encrypted. // IVType.None is used by MembershipProvider which requires compatibility even in SP2 mode. bool createIV = ((ivType != IVType.None) && (CompatMode > MachineKeyCompatibilityMode.Framework20SP1)); if (fEncrypt && createIV) { byte[] iv = null; int ivLength = (useValidationSymAlgo ? _IVLengthValidation : _IVLengthDecryption); switch (ivType) { case IVType.Hash: iv = GetIVHash(buf, ivLength); break; case IVType.Random: iv = new byte[ivLength]; RandomNumberGenerator.GetBytes(iv); break; } Debug.Assert(iv != null, "Invalid value for IVType: " + ivType.ToString("G")); cs.Write(iv, 0, iv.Length); } cs.Write(buf, start, length); if (fEncrypt && modifier != null) { cs.Write(modifier, 0, modifier.Length); } cs.FlushFinalBlock(); byte[] paddedData = ms.ToArray(); byte[] bData; cs.Close(); ReturnCryptoTransform(fEncrypt, oDesEnc, useValidationSymAlgo, useLegacyMode); // DevDiv Bugs 137864: Strip Random or Hashed IV from beginning of unencrypted data if (!fEncrypt && createIV) { // strip off the first bytes that were either random bits or a hash of the original data // either way it is always equal to the key length int ivLength = (useValidationSymAlgo ? _IVLengthValidation : _IVLengthDecryption); int bDataLength = paddedData.Length - ivLength; // valid if the data is long enough to have included the padding if (bDataLength >= 0) { bData = new byte[bDataLength]; // copy from the padded data to non-padded buffer bData. // dont bother with copy if the data is entirely the padding if (bDataLength > 0) { Buffer.BlockCopy(paddedData, ivLength, bData, 0, bDataLength); } } else { // data is not padded because it is not long enough bData = paddedData; } } else { bData = paddedData; } if (!fEncrypt && modifier != null && modifier.Length > 0) { for(int iter=0; iter<modifier.Length; iter++) if (bData[bData.Length - modifier.Length + iter] != modifier[iter]) throw new HttpException(SR.GetString(SR.Unable_to_validate_data)); byte[] bData2 = new byte[bData.Length - modifier.Length]; Buffer.BlockCopy(bData, 0, bData2, 0, bData2.Length); bData = bData2; } return bData; } } 
+8
source

Source code for membership providers is available from Microsoft. Scott Guthrie wrote about this a few years ago.

http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx

0
source

If you want to encode and generate passwords for SimpleMembershipProvider, see https://github.com/k-makarov/MembershipPasswordGenerator

0
source

Source: https://habr.com/ru/post/1434317/