【问题标题】:AspNet Membership Encrypted Password GenerationAspNet 成员加密密码生成
【发布时间】:2019-07-18 14:54:53
【问题描述】:

在我们开始之前,我想明确表示我知道这个问题有多糟糕。这是一个可怕的情况,但我受到一些非常奇怪的规范的限制。

我知道你不仅不应该尝试为这类东西编写自己的包装器,but Microsoft have made it clear this shouldn't even be used。所以在你开始写回复说“你为什么要这样做”之前,请试着理解我已经和我的上级进行了这些对话,但是推动新功能和缺乏时间意味着尽管它是残酷的;尽管如此 - 我在这里。

我们有一个 ASP Net 会员数据库,早在我在这家公司工作之前就开始了,现在拥有大约 4 万用户。我们在 .Net 3.5 中有一个平台,可以让用户登录。

我目前的工作是在 .Net Core 2.1 中编写一个 API,其中一部分是允许用户创建和更新,但问题在于 - 从成员身份迁移到身份不是一种选择,所以我被告知要为 Membership 数据库中的存储过程创建一个包装器。

这几乎是成功的,唯一的问题是;这个问题的主题。通过aspnet_Membership_CreateUser 创建用户我需要以可以在我们的平台上成功验证的方式提交数据。

我最初关注this post,但发现它是为 PasswordFormat 1 - Hashed 设计的;然后我发现我们的用户群使用 PasswordFormat 2 - Encrypted,因此我创建的用户不会验证。

代码看起来像这样

    public bool CreateUser(string userName, string password, string email, string securityQuestion, string securityAnswer, bool isApproved)
    {
        bool success = false;

        //Just so I can attempt to login afterwards
        password = "Hello World!";

        //Our password and password salt need to be base64 encoded before we can save them to the DB
        string salt = Guid.NewGuid().ToString();
        string encryptedSalt = salt.Base64Encode();

        //Concatenate our salt and password
        IEnumerable<byte> saltedpass = salt.GetBytes(Encoding.UTF8).Concat(password.GetBytes(Encoding.UTF8));

        //Use SHA1 to hash more - equivilant to the HASHBYTES('SHA1' T-SQL
        byte[] sha1HashedPass = PasswordHelper.HashBytes(_validationMethod, saltedpass.ToArray(), _validationKey);
        string hashedPass = sha1HashedPass.ToBase64String();

        int errorCode = MembershipCreateUser(_applicationName, userName, hashedPass, encryptedSalt, email, securityQuestion, securityAnswer, isApproved);
        if (errorCode == 0)
        {
            success = true;
        }
        return success;
    }

值得注意的是,_validationKey 是使用该数据库的应用程序之间共享的机器密钥,我将其传递给 SHA1 机制。

所以,撇开故意和可悲的糟糕安全做法不谈; C# 中有没有办法以这种方式生成加密(非散列)密码和盐?

【问题讨论】:

  • 我认为您最好的前进道路是实施 IdentityServer,并使用自定义用户存储(您现有的会员数据库)。这本质上将允许您抽象身份验证层,并为所有未来的开发提供一个良好的工作平台。见:docs.identityserver.io/en/latest
  • 如果还有什么方法可以继续使用hashed,我升级到Bcrypt主要是注释掉引用saltGenerateSalt()等的代码,并使用salt = string.Empty;所以我不会必须更新SQL。 Bcrypt 在内部创建盐。只需要TPRBCrypt.HashPassword(password);。但是,我明白,在你的情况下,这可能是不可能的。

标签: asp.net asp.net-core asp.net-membership


【解决方案1】:

感谢 cmets - 感谢我们能够在我们的平台中支持散列密码;问题出在我的代码上,而不是 ASP Membership。

如前所述,我正在使用originally written in T-SQL 的帖子并尝试构建它的 C# 实现。我对该代码的实现不正确,因此我生成的密码和盐无法通过 ASP Net Membership 进行验证,这在我的原始帖子中并不明显,因为我混淆了 SHA1 散列我的数据的方法。

    //Using hard coded just for example
    string username = "joeborder";
    string password = "Hello World!";
    string salt = "TastySalt";
    Encoding encoder = Encoding.Unicode;    //Encoding was also incorrect

    //Our password and password salt need to be base64 encoded before we can save them to the DB
    string encryptedSalt = salt.Base64Encode();

    //Concatenate our salt and password
    IEnumerable<byte> saltedpass = salt.GetBytes(encoder).Concat(password.GetBytes(encoder));

    //Use SHA1 to hash more - equivilant to the HASHBYTES('SHA1') T-SQL
    var SHA1Hasher = new SHA1CryptoServiceProvider();    //Originally I was using HMACSHA1 which was producing a different output
    byte[] sha1HashedPass = SHA1Hasher.ComputerHash(saltedpass.ToArray());
    string hashedPass = sha1HashedPass.ToBase64String();

    /*
        EXEC aspnet_Membership_CreateUser
            @ApplicationName = "MyApp",
            @UserName = username,
            @Password = hashedPass,
            @PasswordSalt = encryptedSalt,
            ...Etc
    */

然后在我们的 .Net 3.5 应用程序中,下面的代码就可以工作了

    string username = "joeborder";
    string password = "Hello World!";

    if (Membership.ValidateUser(username, password))
    {
        Console.WriteLine("You've gotta be kidding me thats a clutch");
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2010-12-02
    • 2011-04-03
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多