代码之家  ›  专栏  ›  技术社区  ›  iburlakov

ASP的默认哈希算法是什么。NET成员身份使用?

  •  63
  • iburlakov  · 技术社区  · 17 年前

    7 回复  |  直到 15 年前
        1
  •  48
  •   Community Mohan Dere    9 年前

    编辑:不要按原样使用成员资格提供程序,因为它在保护用户密码方面严重不足

    googling "membership provider hashing algorithm" 将这个答案作为第一个结果,以及将要推断的福音,我有责任警告人们不要使用这样的会员资格提供者,也不要使用SHA-1、MD5等哈希来混淆数据库中的密码。

    太长,读不下去了

    Use a key-derivation function like bcrypt, scrypt or (if you need FIPS compliance) PBKDF2

    足够长的时间来计算!

    IdentityReboot newer implementations from Microsoft that Troy Hunt talks about

    tutorial showing folks preciously how easy it is 使用JtR或Hashcat等流行工具暴力破解这些密码哈希。在自定义GPU装备上,SHA1可以在 staggering rate of 48867 million hashes per second ! 有一本免费的词典,比如 rockyou or the like


    默认的哈希是SHA1,但他们也对其进行盐和base64处理:

    public string EncodePassword(string pass, string salt)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(pass);
        byte[] src = Encoding.Unicode.GetBytes(salt);
        byte[] dst = new byte[src.Length + bytes.Length];
        Buffer.BlockCopy(src, 0, dst, 0, src.Length);
        Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
        HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
        byte[] inArray = algorithm.ComputeHash(dst);
        return Convert.ToBase64String(inArray);
    }
    

    http://forums.asp.net/p/1336657/2899172.aspx

    如果需要的话,这个SO问题将有助于逆转或复制这种技术。 Reimplement ASP.NET Membership and User Password Hashing in Ruby

    如果您正在制作自定义提供程序,则可以创建哈希和加密算法和方法。

    private byte[] ConvertPasswordForStorage(string Password)
          {
             System.Text.UnicodeEncoding ue = 
          new System.Text.UnicodeEncoding();
             byte[] uePassword = ue.GetBytes(Password);
             byte[] RetVal = null;
             switch (_PasswordFormat)
             {
                case MembershipPasswordFormat.Clear:
                   RetVal = uePassword;
                   break;
                case MembershipPasswordFormat.Hashed:
    
                   HMACSHA1 SHA1KeyedHasher = new HMACSHA1();
                   SHA1KeyedHasher.Key = _ValidationKey;
                   RetVal = SHA1KeyedHasher.ComputeHash(uePassword);
                   break;
                case MembershipPasswordFormat.Encrypted:
                   TripleDESCryptoServiceProvider tripleDes = new 
           TripleDESCryptoServiceProvider();
                   tripleDes.Key = _DecryptionKey;
                   tripleDes.IV = new byte[8];
                   MemoryStream mStreamEnc = new MemoryStream();
                   CryptoStream cryptoStream = new CryptoStream(mStreamEnc, 
            tripleDes.CreateEncryptor(), 
          CryptoStreamMode.Write);
    
                   cryptoStream.Write(uePassword, 0, uePassword.Length);
                   cryptoStream.FlushFinalBlock();
                   RetVal = mStreamEnc.ToArray();
                   cryptoStream.Close();
                   break;
    
             }
             return RetVal;
          }
    
    private string GetHumanReadablePassword(byte[] StoredPassword)
          {
             System.Text.UnicodeEncoding ue = new System.Text.UnicodeEncoding();
             string RetVal = null;
             switch (_PasswordFormat)
             {
                case MembershipPasswordFormat.Clear:
                   RetVal = ue.GetString(StoredPassword);
                   break;
                case MembershipPasswordFormat.Hashed:
                   throw new ApplicationException(
            "Password cannot be recovered from a hashed format");
    
                case MembershipPasswordFormat.Encrypted:
                   TripleDESCryptoServiceProvider tripleDes = 
            new TripleDESCryptoServiceProvider();
                   tripleDes.Key = _DecryptionKey;
                   tripleDes.IV = new byte[8];
                   CryptoStream cryptoStream = 
            new CryptoStream(new MemoryStream(StoredPassword), 
          tripleDes.CreateDecryptor(), CryptoStreamMode.Read);
                   MemoryStream msPasswordDec = new MemoryStream();
                   int BytesRead = 0;
                   byte[] Buffer = new byte[32];
                   while ((BytesRead = cryptoStream.Read(Buffer, 0, 32)) > 0)
                   {
                      msPasswordDec.Write(Buffer, 0, BytesRead);
    
                   }
                   cryptoStream.Close();
    
                   RetVal = ue.GetString(msPasswordDec.ToArray());
                   msPasswordDec.Close();
                   break;
             }
             return RetVal;
          }
    

    http://msdn.microsoft.com/en-us/library/aa479048.aspx

        2
  •  37
  •   Muleskinner    8 年前

    above answer by Ryan Christensen

    这是我在客户解决方案中实现的一个工作示例:

    public string Hash(string value, string salt)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(value);
            byte[] src = Convert.FromBase64String(salt);
            byte[] dst = new byte[src.Length + bytes.Length];
            Buffer.BlockCopy(src, 0, dst, 0, src.Length);
            Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
            HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
            byte[] inArray = algorithm.ComputeHash(dst);
            return Convert.ToBase64String(inArray);
        }
    
        3
  •  28
  •   MikeD    15 年前

    默认哈希算法类型为SHA1。有两种方法可以改变这一点。

    Machine Key configuration page from IIS 7 administration tool

    <membership
        defaultProvider="provider name"
        userIsOnlineTimeWindow="number of minutes"
        hashAlgorithmType="SHA1">
        <providers>...</providers>
    </membership>
    

    根据文档 hashAlgorithmType 属性可以是提供的任何一个。网络哈希算法类型。稍加挖掘,就会发现ASP。净2、3和3.5是 MD5 , RIPEMD160 , SHA1 , SHA256 , SHA384 , SHA512 这里的重要部分是所有这些类都继承自 HashAlgorithm .

    的价值 属性也可以是来自 cryptoNameMapping machine.config文件中的元素。如果你需要第三方哈希算法,你可以使用它。machine.config文件通常可以在以下位置找到 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG 如果你正在使用ASP。Net 2或更高版本。您可以阅读更多关于设置这些值的信息 here .

        4
  •  26
  •   phloopy    15 年前

    中的默认哈希算法更改为HMACSHA256。NET 4.0框架。

    请注意,与SHA-1不同,HMAC SHA-256是一个密钥哈希。如果你的哈希值表现得不确定,你可能还没有设置密钥,迫使它使用随机密钥。类似于以下内容的东西可能是罪魁祸首(这是我刚刚花了一个小时才弄清楚的:p)。

    HashAlgorithm.Create(Membership.HashAlgorithmType)
    

    如果你想让它与现有的提供者一起工作,你可以使用以下命令将其还原为以前的默认值 this guide .

        5
  •  3
  •   Edwin de Koning Umair Baig    15 年前

    哈希算法中有一个更正,您必须使用:

    byte[] src = Convert.FromBase64String(salt);
    

    byte[] src = Encoding.Unicode.GetBytes(salt);
    

    阅读文章 http://svakodnevnica.com.ba/index.php?option=com_kunena&func=view&catid=4&id=4&Itemid=5&lang=en#6

        6
  •  1
  •   jitin14    6 年前

    1. Zetetic 哈希算法PBKDF2比SHA1或SHA256-SHA512等要好得多。PBKDF2、SCRYPT或ARGON2等最新算法在哈希方面处于领先地位。但是在这种情况下使用PBKDF2是有用的,因为它是由实现的。净入 Rfc2898DeriveBytes

      a.Zetetic默认使用5000次迭代。可定制,如果您使用 Pbkdf2Hash256K

      b.玉米的使用 Rfc2898衍生字节 Rfc2898衍生字节 基于 HMACSHA1

    2. 好消息!我已经定制了 Rfc2898衍生字节 使用 HMACSHA512 通过128000次迭代,SQLMembershipProvider可以使用到目前为止还不可用的PBKDF2。为了实现这一目标,我结合了 Zetetic's 代码与我的实现 Rfc2898衍生字节 如下图所示:

    using System.Security.Cryptography;

    namespace custom.hashing.keyderivation
    {
    /// <summary>
    /// This derived class of PBKDF2Hash provided necessary capabilities to SQLMembershipProvider in order to hash passwords in PBKDF2 way with 128,000 iterations.
    /// </summary>
    public class PBKDF2Hash : KeyedHashAlgorithm
    {
        private const int kHashBytes = 64;
    
        private System.IO.MemoryStream _ms;
    
        public int WorkFactor { get; set; }
    
        public PBKDF2Hash()
            : base()
        {
            this.WorkFactor = 128000;
            this.Key = new byte[32]; // 32 Bytes will give us 256 bits.
            using (var rngCsp = new RNGCryptoServiceProvider())
            {
                // Fill the array with cryptographically secure random bytes.
                rngCsp.GetBytes(this.Key);
            }
        }
    
        /// <summary>
        /// Hash size in bits
        /// </summary>
        public override int HashSize
        {
            get
            {
                return kHashBytes * 8;
            }
        }
    
        protected override void HashCore(byte[] array, int ibStart, int cbSize)
        {
            (_ms = _ms ?? new System.IO.MemoryStream()).Write(array, ibStart, cbSize);
        }
    
        protected override byte[] HashFinal()
        {
            if (this.Key == null || this.Key.Length == 0)
            {
                throw new CryptographicException("Missing KeyedAlgorithm key");
            }
    
            _ms.Flush();
    
            var arr = _ms.ToArray();
    
            _ms = null;
    
            using (var hmac = new HMACSHA512())
            {
                return new MyRfc2898DeriveBytes(arr, this.Key, this.WorkFactor, hmac).GetBytes(kHashBytes);
            }
        }
    
        public override void Initialize()
        {
            _ms = null;
        }
    }
    
    // ==++==
    // 
    //   Copyright (c) Microsoft Corporation.  All rights reserved.
    // 
    // ==--==
    // <OWNER>Microsoft</OWNER>
    // 
    
    //
    // Rfc2898DeriveBytes.cs
    //
    
    // This implementation follows RFC 2898 recommendations. See http://www.ietf.org/rfc/Rfc2898.txt
    /// <summary>
    /// Microsoft has implemented PBKDF2 but with HMACSHA1. We are customizing this class to use HMACSHA512 in hashing process.
    /// </summary>
    public class MyRfc2898DeriveBytes : DeriveBytes
    {
        private byte[] m_buffer;
        private byte[] m_salt;
        private HMAC m_hmac;  // The pseudo-random generator function used in PBKDF2
    
        private uint m_iterations;
        private uint m_block;
        private int m_startIndex;
        private int m_endIndex;
    
        private int m_blockSize;
    
        //
        // public constructors
        //
    
        // This method needs to be safe critical, because in debug builds the C# compiler will include null
        // initialization of the _safeProvHandle field in the method.  Since SafeProvHandle is critical, a
        // transparent reference triggers an error using PasswordDeriveBytes.
        [SecuritySafeCritical]
        public MyRfc2898DeriveBytes(byte[] password, byte[] salt, int iterations, HMAC hmac)
        {
            Salt = salt;
            IterationCount = iterations;
            hmac.Key = password;
            m_hmac = hmac;
            // m_blockSize is in bytes, HashSize is in bits. 
            m_blockSize = hmac.HashSize >> 3;
    
            Initialize();
        }
    
        //
        // public properties
        //
    
        public int IterationCount
        {
            get { return (int)m_iterations; }
            set
            {
                if (value <= 0)
                    throw new ArgumentOutOfRangeException("value", "Error: Iteration count is zero or less");
    
                m_iterations = (uint)value;
                Initialize();
            }
        }
    
        public byte[] Salt
        {
            get { return (byte[])m_salt.Clone(); }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                if (value.Length < 8)
                    throw new ArgumentException("Error: Salt size is less than 8");
    
                m_salt = (byte[])value.Clone();
                Initialize();
            }
        }
    
        //
        // public methods
        //
    
        public override byte[] GetBytes(int cb)
        {
            if (cb <= 0)
            {    throw new ArgumentOutOfRangeException("cb", "Error: Hash size is zero or less"); }
    
            Contract.Assert(m_blockSize > 0);
    
            byte[] password = new byte[cb];
    
            int offset = 0;
            int size = m_endIndex - m_startIndex;
            if (size > 0)
            {
                if (cb >= size)
                {
                    Buffer.BlockCopy(m_buffer, m_startIndex, password, 0, size);
                    m_startIndex = m_endIndex = 0;
                    offset += size;
                }
                else
                {
                    Buffer.BlockCopy(m_buffer, m_startIndex, password, 0, cb);
                    m_startIndex += cb;
                    return password;
                }
            }
    
            Contract.Assert(m_startIndex == 0 && m_endIndex == 0, "Invalid start or end index in the internal buffer.");
    
            while (offset < cb)
            {
                byte[] T_block = Func();
                int remainder = cb - offset;
                if (remainder > m_blockSize)
                {
                    Buffer.BlockCopy(T_block, 0, password, offset, m_blockSize);
                    offset += m_blockSize;
                }
                else
                {
                    Buffer.BlockCopy(T_block, 0, password, offset, remainder);
                    offset += remainder;
                    Buffer.BlockCopy(T_block, remainder, m_buffer, m_startIndex, m_blockSize - remainder);
                    m_endIndex += (m_blockSize - remainder);
                    return password;
                }
            }
            return password;
        }
    
        public override void Reset()
        {
            Initialize();
        }
    
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
    
            if (disposing)
            {
                if (m_hmac != null)
                {
                    ((IDisposable)m_hmac).Dispose();
                }
    
                if (m_buffer != null)
                {
                    Array.Clear(m_buffer, 0, m_buffer.Length);
                }
                if (m_salt != null)
                {
                    Array.Clear(m_salt, 0, m_salt.Length);
                }
            }
        }
    
        private void Initialize()
        {
            if (m_buffer != null)
                Array.Clear(m_buffer, 0, m_buffer.Length);
            m_buffer = new byte[m_blockSize];
            m_block = 1;
            m_startIndex = m_endIndex = 0;
        }
    
        internal static byte[] GetBytesFromInt(uint i)
        {
            return unchecked(new byte[] { (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte)i });
        }
    
        // This function is defined as follow :
        // Func (S, i) = HMAC(S || i) | HMAC2(S || i) | ... | HMAC(iterations) (S || i) 
        // where i is the block number.
        private byte[] Func()
        {
            byte[] INT_block = GetBytesFromInt(m_block);
    
            m_hmac.TransformBlock(m_salt, 0, m_salt.Length, null, 0);
            m_hmac.TransformBlock(INT_block, 0, INT_block.Length, null, 0);
            m_hmac.TransformFinalBlock(new byte[0], 0, 0);
            byte[] temp = m_hmac.Hash;
            m_hmac.Initialize();
    
            byte[] ret = temp;
            for (int i = 2; i <= m_iterations; i++)
            {
                m_hmac.TransformBlock(temp, 0, temp.Length, null, 0);
                m_hmac.TransformFinalBlock(new byte[0], 0, 0);
                temp = m_hmac.Hash;
                for (int j = 0; j < m_blockSize; j++)
                {
                    ret[j] ^= temp[j];
                }
                m_hmac.Initialize();
            }
    
            // increment the block count.
            if (m_block == uint.MaxValue)
            { throw new InvalidOperationException("Derived key too long."); }
    
            m_block++;
            return ret;
        }
    }
    

    创建此类后,请执行以下操作:

    • System.Security.Cryptography.CryptoConfig.AddAlgorithm(typeof(custom.hashing.keyderivation.PBKDF2Hash), "PBKDF2Hash_HB");

    • 并将web.config更改为:

      <membership defaultProvider="sitecore" hashAlgorithmType="PBKDF2Hash_HB">

    构建此答案的参考文献来自:

        7
  •  0
  •   Quintus Marais    11 年前

    我附上了一个代码片段,显示了上文F中Rawbert的答案中的代码#

    open System
    open System.Security.Cryptography
    open System.Text
    
    module PasswordHelper =
        let EncodePassword(pass : string, salt : string) =
            let bytes = Encoding.Unicode.GetBytes(pass)
            let src = Convert.FromBase64String(salt)
            let dst : byte array = Array.zeroCreate (src.Length + bytes.Length)
            Buffer.BlockCopy(src, 0, dst, 0, src.Length)
            Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length)
            let algorithm = HashAlgorithm.Create("SHA1")
            let inArray = algorithm.ComputeHash(dst)
            Convert.ToBase64String(inArray)
    

    推荐文章