【问题标题】:Changing Storage of Password to Storing of Hashes in C# Forms将密码的存储更改为 C# 表单中的哈希存储
【发布时间】:2019-01-30 15:30:45
【问题描述】:

我当前的项目是使用 Microsoft 的 Membership 来管理用户的凭据。

目前,它将密码以纯文本形式存储到 SQL DB 中。

我想更改它以存储哈希值,或者加密/隐藏密码列。


当前代码:

protected void BtnSubmit_Click(object sender, EventArgs e)
    {
        Page.Validate();

        if (Page.IsValid)
        {
            NAME_OF_TABLE_Provider provider = new NAME_OF_TABLE_Provider();

            string userName = SPContext.Current.Web.CurrentUser.Name;
            MembershipUserCollection userMembership = Membership.GetAllUsers();

            MembershipUser membershipUser = userMembership[userName];

            if (membershipUser != null)
            {
                try
                {
                    membershipUser.ChangePassword(OldPassword.Text, NewPassword.Text);
                    ConfirmPanel.Visible = true;
                    InvalidPanel.Visible = false;
                    Message.InnerText = "The password is changed successfully";
                }
                catch (Exception ex)
                {
                    ConfirmPanel.Visible = false;
                    InvalidPanel.Visible = true;
                    InvalidPassword.InnerText = "The password is not strong. Please verify.";
                }
            }
        }
    }

#1 可能(?)解决方案:HashBytes

INSERT INTO <tbl> (..., passwd) values (...., HashBytes('SHA1', @password))

SELECT HashBytes('SHA1', @password);

#2 可能(?)解决方案:C# 存储哈希

    static void Main(string[] args)
    {
        //Store a password hash:
        PasswordHash hash = new PasswordHash("password");
        byte[] hashBytes = hash.ToArray();
        //For testing purposes
        Console.WriteLine(Convert.ToBase64String(hashBytes));

        //Check password against a stored hash
        byte[] hashBytes2 = hashBytes;//read from store.
        PasswordHash hash2 = new PasswordHash(hashBytes2);

        if (!hash.Verify("password"))
        {
            throw new System.UnauthorizedAccessException();
        }
        else
        {
            Console.WriteLine("True");
        }
        Console.ReadLine();
    }

    }

    public sealed class PasswordHash
    {
        const int SaltSize = 16, HashSize = 20, HashIter = 10000;
        readonly byte[] _salt, _hash;
        public PasswordHash(string password)
        {
            new RNGCryptoServiceProvider().GetBytes(_salt = new byte[SaltSize]);
            _hash = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize);
        }
        public PasswordHash(byte[] hashBytes)
        {
            Array.Copy(hashBytes, 0, _salt = new byte[SaltSize], 0, SaltSize);
            Array.Copy(hashBytes, SaltSize, _hash = new byte[HashSize], 0, HashSize);
        }
        public PasswordHash(byte[] salt, byte[] hash)
        {
            Array.Copy(salt, 0, _salt = new byte[SaltSize], 0, SaltSize);
            Array.Copy(hash, 0, _hash = new byte[HashSize], 0, HashSize);
        }
        public byte[] ToArray()
        {
            byte[] hashBytes = new byte[SaltSize + HashSize];
            Array.Copy(_salt, 0, hashBytes, 0, SaltSize);
            Array.Copy(_hash, 0, hashBytes, SaltSize, HashSize);
            return hashBytes;
        }
        public byte[] Salt { get { return (byte[])_salt.Clone(); } }
        public byte[] Hash { get { return (byte[])_hash.Clone(); } }
        public bool Verify(string password)
        {
            byte[] test = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize);
            for (int i = 0; i < HashSize; i++)
                if (test[i] != _hash[i])
                    return false;
            return true;
        }

#3 可能(?)解决方案:Transact-SQL 加密单列

https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/encrypt-a-column-of-data?view=sql-server-2017#TsqlProcedure


我可以知道正确的方法是什么吗?谢谢。

【问题讨论】:

    标签: c# sql encryption hash sql-server-2014


    【解决方案1】:

    毫无疑问,任何解决方案都比当前的解决方案更好。

    • 第一个解决方案看起来很可靠,但我无法确定是否使用了盐。如果不是,那就是劣势。您现在也依赖此数据库供应商,无法切换。

    • 第二个解决方案看起来不错,但我没仔细看,你应该去CodeReview,他们会审查工作代码以寻求改进。

    • 最后一个解决方案并不是真正的解决方案。出于某种原因,密码是散列而不是exncrypted。如果可以解密它们,那么获得系统访问权限并窃取它们的攻击者将拥有与你一样的解密手段访问权限。所以这是一层不便,而不是安全。

    所以选择第二个,让别人检查它是否存在弱点或错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-07
      • 1970-01-01
      • 2018-06-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 2018-05-12
      相关资源
      最近更新 更多