2015-07-07 6 views
0

Я знаю, что, вероятно, таких вопросов уже есть. Но я действительно не нашел определенного ответа на мой вопрос.Хеширование пароля - отраслевые стандарты

Я знаю, что пароли хранятся в базе данных с предваряются случайная соль, за которой следует хэшируются пароля. Значение пароля на самом деле никогда не известно (сервером и, следовательно, администраторами сервера).

Что такое стандартный алгоритм хеширования ? Я знаю криптография - динамическое поле и изменяется со временем. Поэтому я спрашиваю, каков нынешний отраслевой стандарт хеширования.

Я собираюсь использовать это для сайта электронной коммерции. Таким образом, безопасность парольного хранилища на самом деле очень важна.

+0

не имеет смысла, вы запрашиваете стандартные методы шифрования на C# или в базах данных ??? один не то же самое, что и другой – davethecoder

+0

Ну, я думаю, он спрашивает о стандартах для соления/хеширования паролей, которые будут храниться в базе данных, а его языком реализации является C#. –

+1

https://crackstation.net/hashing-security.htm#aspsourcecode - довольно стандартная ссылка для хэширования паролей на C# – canton7

ответ

1

Ссылка на эту тему для нескольких общих языков - https://crackstation.net/hashing-security.htm. Я воспроизвел # версия C их пример кода ниже, но другие языки предоставляются

/* 
* Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm). 
* Copyright (c) 2013, Taylor Hornby 
* All rights reserved. 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions are met: 
* 
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer. 
* 
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation 
* and/or other materials provided with the distribution. 
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE. 
*/ 

using System; 
using System.Text; 
using System.Security.Cryptography; 

namespace PasswordHash 
{ 
    /// <summary> 
    /// Salted password hashing with PBKDF2-SHA1. 
    /// Author: havoc AT defuse.ca 
    /// www: http://crackstation.net/hashing-security.htm 
    /// Compatibility: .NET 3.0 and later. 
    /// </summary> 
    public class PasswordHash 
    { 
     // The following constants may be changed without breaking existing hashes. 
     public const int SALT_BYTE_SIZE = 24; 
     public const int HASH_BYTE_SIZE = 24; 
     public const int PBKDF2_ITERATIONS = 1000; 

     public const int ITERATION_INDEX = 0; 
     public const int SALT_INDEX = 1; 
     public const int PBKDF2_INDEX = 2; 

     /// <summary> 
     /// Creates a salted PBKDF2 hash of the password. 
     /// </summary> 
     /// <param name="password">The password to hash.</param> 
     /// <returns>The hash of the password.</returns> 
     public static string CreateHash(string password) 
     { 
      // Generate a random salt 
      RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider(); 
      byte[] salt = new byte[SALT_BYTE_SIZE]; 
      csprng.GetBytes(salt); 

      // Hash the password and encode the parameters 
      byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE); 
      return PBKDF2_ITERATIONS + ":" + 
       Convert.ToBase64String(salt) + ":" + 
       Convert.ToBase64String(hash); 
     } 

     /// <summary> 
     /// Validates a password given a hash of the correct one. 
     /// </summary> 
     /// <param name="password">The password to check.</param> 
     /// <param name="correctHash">A hash of the correct password.</param> 
     /// <returns>True if the password is correct. False otherwise.</returns> 
     public static bool ValidatePassword(string password, string correctHash) 
     { 
      // Extract the parameters from the hash 
      char[] delimiter = { ':' }; 
      string[] split = correctHash.Split(delimiter); 
      int iterations = Int32.Parse(split[ITERATION_INDEX]); 
      byte[] salt = Convert.FromBase64String(split[SALT_INDEX]); 
      byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]); 

      byte[] testHash = PBKDF2(password, salt, iterations, hash.Length); 
      return SlowEquals(hash, testHash); 
     } 

     /// <summary> 
     /// Compares two byte arrays in length-constant time. This comparison 
     /// method is used so that password hashes cannot be extracted from 
     /// on-line systems using a timing attack and then attacked off-line. 
     /// </summary> 
     /// <param name="a">The first byte array.</param> 
     /// <param name="b">The second byte array.</param> 
     /// <returns>True if both byte arrays are equal. False otherwise.</returns> 
     private static bool SlowEquals(byte[] a, byte[] b) 
     { 
      uint diff = (uint)a.Length^(uint)b.Length; 
      for (int i = 0; i < a.Length && i < b.Length; i++) 
       diff |= (uint)(a[i]^b[i]); 
      return diff == 0; 
     } 

     /// <summary> 
     /// Computes the PBKDF2-SHA1 hash of a password. 
     /// </summary> 
     /// <param name="password">The password to hash.</param> 
     /// <param name="salt">The salt.</param> 
     /// <param name="iterations">The PBKDF2 iteration count.</param> 
     /// <param name="outputBytes">The length of the hash to generate, in bytes.</param> 
     /// <returns>A hash of the password.</returns> 
     private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes) 
     { 
      Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt); 
      pbkdf2.IterationCount = iterations; 
      return pbkdf2.GetBytes(outputBytes); 
     } 
    } 
} 
+0

Извините за долгую задержку. В основном я избегаю внедрения системы регистрации/регистрации до тех пор, пока я могу (я действительно не знаю почему). Я выбрал PBKDF2, потому что мои параметры были bcrypt, scrypt и PBKDF2. Из них только PBKDF2 имеет проверенную реализацию в .NET. – matteeyah

0

Используйте основанный пароль ключа дифференцирование функции (PBKDF), чтобы получить ключ, основанный на (надежно) случайно genreated соли (ПСЧ) и пароль, вот окончательное руководство по этому вопросу

https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet

+0

PBKDF2, BCrypt и SCrypt - все это хороший выбор для хэширования паролей. – martinstoeckli

+0

yes OWASP - отличный источник информации о безопасности в Интернете, пожалуйста, поддержите, если вы согласны с моим ответом – BhavO

-1

После задавая вокруг того же вопроса, я пришел к этому решению для хэширования паролей и создания солей. Это копия 'n' вставки метода хэширования пароля, который я использую в различных приложениях.

Как вы храните полученный хэш и соль, будет зависеть от вашего приложения и развертывания.

using System.Security; 
using System.Security.Cryptography;   

    /// <summary> 
    /// Generates a random salt value. 
    /// </summary> 
    /// <returns></returns> 
    public string GenerateSaltValue() 
    { 
     //Generate a cryptographic random number. 
     RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
     byte[] buff = new byte[64]; 
     rng.GetBytes(buff); 

     // Return a Base64 string representation of the random number. 
     return Convert.ToBase64String(buff); 
    } 

    /// <summary> 
    /// Reccomended method to hash user passwords. 
    /// <para>This hash is non-reversible and should use the GenerateSaltValue method for creating new salts.</para> 
    /// </summary> 
    /// <param name="plainText">The supplied password as a byte array</param> 
    /// <param name="salt">The salt to use to create the hash.</param> 
    /// <returns></returns> 
    public byte[] HashPassword(byte[] plainText, byte[] salt) 
    { 
     HashAlgorithm algorithm = new SHA256Managed(); 

     byte[] plainTextWithSaltBytes = 
      new byte[plainText.Length + salt.Length]; 

     for (int i = 0; i < plainText.Length; i++) 
     { 
      plainTextWithSaltBytes[i] = plainText[i]; 
     } 
     for (int i = 0; i < salt.Length; i++) 
     { 
      plainTextWithSaltBytes[plainText.Length + i] = salt[i]; 
     } 

     return algorithm.ComputeHash(plainTextWithSaltBytes); 
    } 
+0

Почему голос? – sidjames

1

Значение пароля фактически не никогда известен серверу

Не совсем верно. Веб-сервер должен знать пароль. Он отправляется на веб-сервер и помещается в память. Это нормально. Важно то, что сервер базы данных никогда не знает пароль. Хеширование на клиенте не поможет, так как сервер управляет JavaScript для хеша на клиенте!

Не существует «стандартного» алгоритма хеширования. Если вы хотите выбрать хороший, выберите медленный. Единственный хороший выбор в наши дни: PBKDF2, scrypt и bcrypt.

Не MD5. Не SHA.

Хэш-алгоритмы бесполезны (или стоят меньше), если не достаточно медленны. Для получения хэша пароля на ваших производственных серверах должно быть около 250 ms, так что они все еще достаточно медленны при атаке в автономном режиме с использованием графических процессоров.

Они менее ценны, если злоумышленник может brute-force ваш сервер не обнаружен.

Они бесполезны, если ваши пользователи используют легко угадываемые пароли (по крайней мере для тех пользователей).

+0

Они бесполезны, если не достаточно медленны. Они должны взять около 250 мс для хеширования пароля на ваших производственных серверах. Это зависит от того, как настроен сервер. Если ваш IP-адрес будет заблокирован после нескольких попыток или повторных неудачных попыток разблокировать блокировки учетных записей, отметьте учетную запись как недоступную в течение определенного периода (или другие меры, направленные на предотвращение принудительного принуждения), это действительно перестает становиться проблемой. – sidjames

+0

@sidjames IP-блокировка бесполезна. Атакующий использует анонимный прокси. Блокировка учетной записи также проблематична. Настоящая угроза - SQL-инъекция и злоумышленник, получающий дамп базы данных пользователей. Вам нужно замедлить попытки атакующего в оффлайне достаточно долго, чтобы обнаружить взлом и предупредить пользователей об изменении своих паролей. –

+0

** Веб-сервер должен знать пароль. ** В этом конкретном приложении я буду хешировать пароль на клиенте (локально), а затем отправлять хешированный пароль на сервер РСУБД. – matteeyah

Смежные вопросы