密码散列 - 行业标准 [英] Password hashing - Industry Standards

查看:120
本文介绍了密码散列 - 行业标准的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这可能有很多这样的问题。但是,我真的没有找到我的问题的确切答案。



我知道密码存储在数据库中,并带有前缀随机盐后跟散列密码。密码的值实际上是永远不会被知道的(服务器和服务器管理员)。

什么是标准哈希算法?我知道加密技术是一个动态字段,随时间而变化。所以我问什么是目前的哈希行业标准。

我打算将它用于电子商务网站。因此,密码存储的安全性实际上是非常重要的。 解决方案

href =https://crackstation.net/hashing-security.htm =nofollow> https://crackstation.net/hashing-security.htm 。我已经复制了下面的代码示例的C#版本,但是提供了其他语言。

*
*使用PBKDF2密码散列(http://crackstation.net/hashing-security.htm)。
* Copyright(c)2013,Taylor Hornby
*保留所有权利。
*
*在符合以下条件的情况下,允许以源代码和二进制形式重新分发和使用(无论是否带有
*修改):
*
* 1 。源代码的重新分配必须保留上述版权声明,
*此条件列表和以下免责声明。
*
* 2.以二进制形式重新分配必须在文档
*和/或提供的其他材料中复制上述版权声明,
*此条件列表和以下免责声明与分配。
*
*本软件由版权所有者和贡献者按原样
*提供,并且不提供任何明示或暗示的担保,包括但不限于所隐含的
*适销性和针对特定用途的适用性保证
*不予理睬。在任何情况下,版权所有者或贡献者均不应对任何直接,间接,附带,特殊,惩戒性或
*后果性损害(包括但不限于采购
) *替代商品或服务;使用,数据或利润损失;或商业
*中断),不论是以任何责任理论为依据,无论是b $ b *合同,严格赔偿责任或民事侵权行为(包括疏忽)或以其他方式)
*以使用本软件的任何方式出现,即使已被告知
*这种损失的可能性。
* /

使用System;
使用System.Text;
使用System.Security.Cryptography;

namespace PasswordHash
{
///< summary>
///使用PBKDF2-SHA1进行密码哈希。
///作者:havoc AT defuse.ca
/// www:http://crackstation.net/hashing-security.htm
///兼容性:.NET 3.0及更高版本。
///< / summary>
public class PasswordHash
{
//以下常量可以在不破坏现有散列的情况下进行更改。
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>
///创建密码的盐渍PBKDF2散列。
///< / summary>
///< param name =password>哈希密码。< / param>
///< returns>密码的散列。< / returns>
public static string CreateHash(string password)
{
//产生一个随机salt
RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
byte [] salt =新字节[SALT_BYTE_SIZE];
csprng.GetBytes(salt);

//哈希密码并对参数进行编码
byte [] hash = PBKDF2(password,salt,PBKDF2_ITERATIONS,HASH_BYTE_SIZE);
return PBKDF2_ITERATIONS +:+
Convert.ToBase64String(salt)+:+
Convert.ToBase64String(hash);
}

///< summary>
///验证密码是否为正确密码。
///< / summary>
///< param name =password>要检查的密码。< / param>
///< param name =correctHash>正确密码的哈希。< / param>
///< returns>如果密码正确,则为真。否则为假。< / returns>
public static bool ValidatePassword(string password,string correctHash)
{
//从哈希中提取参数$ b $ char [] delimiter = {':'};
string [] split = correctHash.Split(delimiter);
int迭代= 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);
返回SlowEquals(hash,testHash);
}

///< summary>
///在长度恒定的时间内比较两个字节数组。这种比较使用
///方法,因此无法使用定时攻击从
///联机系统中提取密码哈希值,然后进行脱机攻击。
///< / summary>
///< param name =a>第一个字节数组。< / param>
///< param name =b>第二个字节数组。< / param>
///< returns>如果两个字节数组相等,则为真。否则为假。< / returns>
private static bool SlowEquals(byte [] a,byte [] b)
{
uint diff =(uint)a.Length ^(uint)b.Length;
for(int i = 0; i diff | =(uint)(a [i] ^ b [i] );
返回diff == 0;
}

///< summary>
///计算密码的PBKDF2-SHA1散列。
///< / summary>
///< param name =password>哈希密码。< / param>
///< param name =salt>盐。< / param>
///< param name =iterations> PBKDF2迭代计数< / param>
///< param name =outputBytes>要生成的哈希长度,以字节为单位。< / param>
///< returns>密码的散列。< / returns>
private static byte [] PBKDF2(string password,byte [] salt,int iterations,int outputBytes)
{
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password,salt);
pbkdf2.IterationCount =迭代;
return pbkdf2.GetBytes(outputBytes);
}
}
}


I know there are probably a lot of questions like this already. But, I really haven't found the definite answer for my question.

I know that passwords are stored in the database with a prepended random salt followed by the hashed password. The value of the password is actually never known (by the server and thus the server admins).

What is the standard hashing algorithm? I know cryptography is a dynamic field and changes with time. So I'm asking what's the current industry standard for hashing.

I'm going to be using this for a e-commerce site. So password storage security is actually very important.

解决方案

The go-to reference on this topic for a few common languages is https://crackstation.net/hashing-security.htm. I've reproduced the C# version of their code sample below, but other languages are provided

/* 
 * 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);
        }
    }
}

这篇关于密码散列 - 行业标准的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆