Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 有效的密码加密_Asp.net_Security_Encryption_Hash - Fatal编程技术网

Asp.net 有效的密码加密

Asp.net 有效的密码加密,asp.net,security,encryption,hash,Asp.net,Security,Encryption,Hash,我已经看了StackOverflow问题,我想在注册(web应用程序)时有效地散列我的密码,然后能够在登录时检查它们是否正确。我使用的是VB,但使用C#很舒服 我很想使用Jeff Atwood在中描述的加密类,因为它非常容易理解。它有一个散列类,但我不知道如何“登录”并在散列后比较散列。这是Jeff使用其加密类演示的哈希方法: Sub DemoHash() Dim d As New Encryption.Data( _ "{ts '2004-10-09 08:10:04'

我已经看了StackOverflow问题,我想在注册(web应用程序)时有效地散列我的密码,然后能够在登录时检查它们是否正确。我使用的是VB,但使用C#很舒服

我很想使用Jeff Atwood在中描述的加密类,因为它非常容易理解。它有一个散列类,但我不知道如何“登录”并在散列后比较散列。这是Jeff使用其加密类演示的哈希方法:

Sub DemoHash()
    Dim d As New Encryption.Data( _
        "{ts '2004-10-09 08:10:04'}The world is beautiful and needs caring by its children")

    Dim hash As New Encryption.Hash(Encryption.Hash.Provider.SHA1)
    Dim hash2 As New Encryption.Hash(Encryption.Hash.Provider.SHA256)
    Dim hash3 As New Encryption.Hash(Encryption.Hash.Provider.SHA384)
    Dim hash4 As New Encryption.Hash(Encryption.Hash.Provider.SHA512)
    Dim hash5 As New Encryption.Hash(Encryption.Hash.Provider.MD5)
    Dim hash6 As New Encryption.Hash(Encryption.Hash.Provider.CRC32)

    hash.Calculate(d)
    hash2.Calculate(d)
    hash3.Calculate(d)
    hash4.Calculate(d)
    hash5.Calculate(d)

    Console.WriteLine("SHA1:   " & hash.Value.Hex)
    Console.WriteLine("SHA256: " & hash2.Value.Hex)
    Console.WriteLine("SHA384: " & hash3.Value.Hex)
    Console.WriteLine("SHA512: " & hash4.Value.Hex)
    Console.WriteLine("MD5:    " & hash5.Value.Hex)
    Console.WriteLine("CRC32:  " & hash6.Calculate(d).Hex)
    Console.WriteLine()

    Dim salt As New Encryption.Data("salty!")
    Console.WriteLine("Salted CRC32:  " & hash6.Calculate(d, salt).Hex)

    Console.WriteLine("Press ENTER to continue...")
    Console.ReadLine()
End Sub
因此,我的问题是:

  • 我可以加密密码(尽管我不打算存储它)并散列字符串。如果我有一个名为“barry”的用户,密码为“fishlegs”,那么存储和检索他的密码的最佳方式是什么

  • 在sqlserver中;二进制或nvarchar是存储散列的最佳选项吗

  • 根据“barry”和他的密码,散列有效地存储了什么?这是一种附加在盐上的“鱼腿”加密吗

  • 密码学很难


    感谢所有能够提供帮助的人……

    不要将加密密码与散列密码混淆;有了一个好的加密哈希函数,您应该不能反转哈希过程来检索原始字符串

    Chad的上述回答是对所涉及概念的一个很好的逐点解释

    这个话题在互联网上被炒得沸沸扬扬;不仅仅是堆栈溢出;说真的,一个简单的网络搜索应该会为你找到一个相当全面的指南


    谢谢你,杰夫,你又散布了一堆错误信息。我想下周我们会看到大量关于散列、加密等的误导性问题,更不用说关于浮点运算的废话了。

    我相信这个过程是这样的:生成一个随机的salt,所以“fishlegs”+“r4nd0mS4lt”得到“fishlegsr4nd0mS4lt”。然后,使用MD5(尽管您可能希望使用SHA256更安全)对其进行散列,得到:593d5518d759b4860188158ef4c71f28。将其和随机生成的盐储存起来。当用户登录时,添加随机salt,然后检查他输入的salt密码是否与数据库中的哈希匹配

  • 散列的全部要点是存储散列而不是明文密码,它们无法恢复(至少非常困难)。它们的设计是单向的,因此检索是不可能的——这就是它们的本质
  • nchar[n]
    可能是最好的选择,因为常见的哈希算法会产生恒定长度的结果(输出160位哈希)。通常的做法是将散列转换为,以便将其存储为ASCII文本
  • salt只是一种将随机比特添加到散列中以使破解过程复杂化的方法。每增加一点盐意味着一个暴力破解程序必须花费两倍的时间(并且使用两倍的内存)
    • 获取用户密码“机密!
    • 生成几个字节的随机salt“s4L75a1T
    • 将它们连接到“s4l75a1tscret!
    • 计算散列“b9797a5b683804eb195b6ba2a5e368ae74394cd3”(这是十六进制的SHA-1)
    • 将hash和salt(都作为十六进制字符串、Base64字符串或任何您喜欢的格式)与用户名和其他用户信息一起存储在数据库中(在本例中,salt只是一个普通字符串,hash是Base64编码的)
    名字姓氏盐哈希 ----------------------------------------------------------------- John Doe s4L75a1T UXL6W2G4BOSZW2UIPENORQ5TNM=
    如果要验证用户密码,只需获取用户名,查找salt,再次执行上述操作,然后查看计算的哈希值与数据库中的哈希值是否匹配。没有(已知的)方法(轻松地)恢复密码。

    嗯,我认为您只是缺少了一些与哈希工作原理相关的基本概念。让我简单解释一下。我将从简单的开始,然后详细说明我的答案,所以请通读整件事,开始时的信息将不安全

    您想要用来存储密码的是一个称为“单向散列”的函数。这意味着,对于您提供给函数的任何输入,相同的输入将始终给出相同的结果。但是,没有数学过程可以让您获取结果字符串并计算出原始输入是什么

    让我们以MD5作为散列函数的示例。如果我在字符串“password”上运行MD5,我将始终得到结果“5f4dcc3b5aa765d61d8327deb882cf99”。然而,如果你只是给某人一个结果字符串(“5f4d…”),他们就不可能应用一些数学过程来“反转”函数并找出它来自“密码”

    这意味着当用户第一次设置密码时,您将对其应用哈希函数,并存储结果。因此,不存储“密码”,而是存储“5f4dcc3b5aa765d61d8327deb882cf99”。然后,当该用户尝试登录时,您将他们键入的任何内容输入登录表单上的密码框,并应用相同的哈希函数。如果您得到的结果与数据库中存储的结果相同,则他们输入的密码必须与最初选择的密码相同,即使您不知道原始密码实际上是什么

    现在,尽管不可能“反转”散列函数,但相同的输入总是给出相同的输出这一事实意味着有人可以简单地建立一个输入/输出对的大型数据库,并使用它来有效地反转散列。这就是所谓的“彩虹桌”。互联网上有很多这样的功能,所以使用简单的散列是不安全的,以防数据库被破坏。也就是说,即使 FirstName LastName Salt Hash ----------------------------------------------------------------- John Doe s4L75a1T uXl6W2g4BOsZW2uipeNornQ5TNM=
    Dim sUserName = "barry"
    Dim sPassWord = "fishlegs"
    Dim mySalt = "A deliciously salty string! fillED WIth all KindS of Junkk(&^&*(£"
    Dim d As New Encryption.Data(mySalt + sUserName + sPassWord)
    Dim hash As New Encryption.Hash(Encryption.Hash.Provider.SHA256)
    hash.Calculate(d)
    Dim sTheSaltedHashedUnPassCombination = hash.Value.Hex;
    SavenewPasswordHashToDatabase(sTheSaltedHashedUnPassCombination)
    
    Dim sThePreviouslyCreatedHashFromTheDatabase = GetHashForUserFromDatabase(usernameProvided)
    Dim mySalt = "A deliciously salty string! fillED WIth all KindS of Junkk(&^&*(£"
    Dim d As New Encryption.Data(mySalt + usernameProvided+ passwordProvided)
    Dim hash As New Encryption.Hash(Encryption.Hash.Provider.SHA256)
    hash.Calculate(d)
    Dim sTheSaltedHashedUnPassCombination = hash.Value.Hex;
    if (sThePreviouslyCreatedHashFromTheDatabase.Equals(sTheSaltedHashedUnPassCombination))
        'UN & Password Valid!
    else
        'UN & PW Invalid!
    end
    
    public static byte[] GetRandomSalt()
    {
      int minSaltSize = 16;
      int maxSaltSize = 32;
    
      Random random = new Random();
      int saltSize = random.Next(minSaltSize, maxSaltSize);
      saltBytes = new byte[saltSize];
      RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
      rng.GetNonZeroBytes(saltBytes); 
      return saltBytes;
    }
    
    public static byte[] ComputeHash(string plainText)
    {
      byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
      HashAlgorithm hash = new SHA256Managed();
      return hash.ComputeHash(plainTextWithSaltBytes);
    }
    
    byte[] passwordHash = ComputeHash(password);
    byte[] salt = GetRandomSalt();
    byte[] saltHash = ComputeHash(salt);
    
    byte[] hashWithSaltBytes = new byte[hashBytes.Length + saltBytes.Length];
    for (int i=0; i < hashBytes.Length; i++)
      hashWithSaltBytes[i] = hashBytes[i];
    for (int i=0; i < saltBytes.Length; i++)
      hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i];
    
    string hashValue = Convert.ToBase64String(hashWithSaltBytes);