为PHP密码提供安全的哈希和盐

目前说MD5是部分不安全的。 考虑到这一点,我想知道哪个机制用于密码保护。

这个问题, 是“双哈希”密码不仅仅是哈希一次? build议多次散列可能是一个好主意,而如何实现单个文件的密码保护? build议使用盐。

我正在使用PHP。 我想要一个安全快速的密码encryption系统。 散列一百万次密码可能会更安全,但也更慢。 如何在速度和安全之间取得良好的平衡? 另外,我更喜欢结果有一个恒定的字符数。

  1. 哈希机制必须在PHP中可用
  2. 它一定是安全的
  3. 它可以使用盐(在这种情况下,所有的盐都是同样好的吗?有没有办法产生好的盐?)

另外,我应该在数据库中存储两个字段(例如,一个使用MD5,另一个使用SHA)? 它会使它更安全还是不安全?

如果我不清楚,我想知道使用哪个哈希函数,以及如何select一个好盐,以便有一个安全和快速的密码保护机制。

相关的问题不完全覆盖我的问题:

PHP和SHA中的MD5有什么不同?
简单的密码encryption
存储密钥的安全方法,asp.net的密码
你将如何在Tomcat 5.5中实现咸味密码?

免责声明 :这个答案是在2008年写的。

从那时起,PHP给了我们password_hashpassword_verify并且自从他们推出以来,他们是推荐的密码散列和检查方法。

答案的理论仍然是一个很好的阅读。

TL; DR

注意事项

  • 不要限制用户可以input密码的字符。 只有白痴才能做到这一点。
  • 不要限制密码的长度。 如果你的用户想要一个超级夸张的句子,那么不要阻止他们使用它。
  • 切勿以纯文本格式存储您的用户密码。
  • 切勿将密码发送给您的用户, 除非他们丢失了密码,并且您发送了临时密码
  • 永远不要以任何方式logging密码。
  • 永远不要使用SHA1或MD5甚至SHA256哈希密码! 现代cookies可以分别超过60亿和1800亿次/秒(分别)。
  • 不要混用bcrypt和hash()的原始输出 ,要么使用hex输出,要么使用base64_encode。 (这适用于任何可能有恶意\0input,这会严重削弱安全性。)

DOS

  • 尽可能使用scrypt; bcrypt,如果你不能。
  • 如果您不能使用bcrypt或scrypt,使用SHA2散列,请使用PBKDF2。
  • 数据库被盗用时重置每个人的密码。
  • 执行一个合理的8-10个字符的最小长度,另外至less需要1个大写字母,1个小写字母,一个数字和一个符号。 这将改善密码的熵,反过来使它更难以破解。 (请参阅“什么是一个很好的密码?”部分辩论。)

为什么哈希密码呢?

哈希密码背后的目标很简单:通过妥协数据库来防止恶意访问用户帐户。 所以密码哈希的目标是通过花费太多时间或金钱来计算明文密码来阻止黑客或黑客。 时间/成本是你的武器最好的威慑。

另一个需要在用户帐户上提供强大的散列的原因是为了给您足够的时间来更改系统中的所有密码。 如果您的数据库被破坏,您将需要足够的时间至lesslocking系统,如果不更改数据库中的每个密码。

Whitehat Security首席技术官Jeremiah Grossman在最近密码恢复之后在其博客中表示 ,要求powershell破解密码保护:

有趣的是,在这个噩梦中,我学到了很多我不知道密码破解,存储和复杂性的知识。 我明白为什么密码存储比密码复杂性更重要。 如果你不知道你的密码是如何存储的,那么你真正可以依赖的是复杂性。 这可能是密码和encryption专家的常识,但对于一般的资讯安全或networking安全专家,我非常怀疑它。

(强调我的)

无论如何,什么使得一个好的密码?

熵 。 (我并不完全赞同兰德尔的观点。)

总之,熵是密码内有多less变化。 当密码只有小写的罗马字母时,只有26个字符。 这并没有太大的变化。 字母数字密码更好,有36个字符。 但是,允许大写和小写的符号大约有96个字符。 这比字母好多了。 一个问题是,为了使我们的密码难忘,我们插入模式 – 这减less了熵。 哎呀!

密码熵很容易估算。 使用全部ASCII字符(大约96个可键入的字符)会产生每个字符6.6的熵,为了将来的安全性,在密码的8个字符处仍然太低(熵为52.679比特)。 但是好消息是:更长的密码和带有unicode字符的密码确实增加了密码的熵,使其更难破解。

Crypto StackExchange站点上有更长的关于密码熵的讨论。 一个好的谷歌search也会带来很多结果。

在与@popnoodles谈话的评论中,他指出,通过使密码scheme更可预测,用X个字母,数字,符号等强制执行 X长度的密码策略实际上可以减less熵。 我同意。 Randomess尽可能地是随机的,总是最安全但最难忘的解决scheme。

据我所知,使世界上最好的密码是一个Catch-22。 要么是它的难以记忆,太可预测,太短,太多的Unicode字符(很难在Windows / Mobile设备上input),太长等等。没有密码对于我们的目的来说是足够好的,所以我们必须保护它们在诺克斯堡。

最佳做法

Bcrypt和scrypt是当前的最佳实践。 Scrypt会比bcrypt更好,但是它并没有被Linux / Unix或networking服务器视为一种标准,并且还没有对其algorithm发表过深入的评论。 但是,algorithm的未来看起来还是有希望的。 如果你正在使用Ruby,那么有一个可以帮助你的scrypt gem ,Node.js现在有它自己的scrypt包。 您可以通过Scrypt扩展或Libsodium扩展使用PHP中的Scrypt (均可在PECL中使用)。

我强烈build议阅读crypt函数的文档,如果你想了解如何使用bcrypt,或者发现自己是一个很好的 包装器,或者使用类似PHPASS的东西来实现更多的传统。 我build议至less12轮bcrypt,如果不是15到18。

当我了解到bcrypt只使用blowfish的关键时间表和一个可变的成本机制时,我改变了使用bcrypt的想法。 后者让你通过增加河豚已经很昂贵的关键时间表来增加成本来强制密码。

平均做法

我几乎无法想象这种情况了。 PHPASS支持PHP 3.0.18到5.3,所以它几乎可以在任何可以想象的安装上使用 – 如果您不确定您的环境是否支持bcrypt,则应该使用它。

但是,假设你根本不能使用bcrypt或者PHPASS。 然后怎样呢?

尝试使用您的环境/应用程序/用户感知可以容忍的最大循环次数的PDKBF2的实现。 我build议的最低数字是2500发。 此外,请确保使用hash_hmac()(如果它可用于使操作难以重现)。

未来的做法

来自PHP 5.5的是一个完整的密码保护库 ,它可以抽象出使用bcrypt的任何麻烦。 虽然我们大多数人在大多数常见的环境中(尤其是共享主机)都使用PHP 5.2和5.3,但是@ircmaxell为即将到来的API构build了一个兼容层 ,它与PHP 5.3.7向后兼容。

密码学概述和免责声明

实际上破解散列密码所需的计算能力不存在。 计算机“破解”密码的唯一方法是重新创build密码并模拟用于保护密码的散列algorithm。 哈希的速度与其被强制使用的能力成线性关系。 更糟糕的是,大多数哈希algorithm可以很容易地并行执行甚至更快。 这就是为什么像bcrypt和scrypt这样昂贵的计划如此重要。

您不可能预见到所有威胁或攻击途径,因此您必须尽最大努力保护您的用户。 如果你不这样做,那么你甚至可能会错过你遭到袭击的事实,直到为时已晚…… 而你要承担责任 。 为了避免这种情况,先行妄想。 攻击自己的软件(内部)并尝试窃取用户凭据,或修改其他用户的帐户或访问其数据。 如果你不testing你的系统的安全性,那么你不能责怪任何人,除了你自己。

最后:我不是密码学家。 无论我说的是我的意见,但是我恰好认为这是基于良好的常识…和大量的阅读。 请记住,要尽可能偏执,尽可能使事情难以入侵,如果您仍然担心,请联系白帽黑客或密码学者,看看他们对您的代码/系统的看法。

一个更短,更安全的答案 – 不要写你自己的密码机制 ,使用一个久经考验的机制。

  • PHP 5.5或更高版本: password_hash()质量好,是PHP核心的一部分。
  • 较早的PHP版本:OpenWall的phpass库比大多数自定义代码要好 – 在WordPress,Drupal等中使用

大多数程序员只是没有专业知识来安全地编写密码相关代码而不会引入漏洞。

快速自检:什么是密码扩展,您应该使用多less次迭代? 如果你不知道答案,你应该使用password_hash() ,因为密码延伸现在是密码机制的关键特性,因为CPU速度更快,并且使用GPU和FPGA以每秒数十亿次的速度破解密码(与GPU)。

例如,您可以使用5台台式机中安装的25个GPU 在6个小时内破解所有8个字符的Windows密码 。 这是暴力,即枚举和检查每个8字符的Windows密码 ,包括特殊字符,而不是字典攻击。 那是在2012年,截至2016年,您可以使用更less的GPU。

对于在普通CPU上运行的Windows密码,也有许多彩虹表攻击,速度非常快。 所有这一切都是因为Windows 仍然 没有使用密码或延长其密码 – 不要像微软那样犯同样的错误!

也可以看看:

  • 关于为什么password_hash()phpass是最好的select。
  • 好的博客文章给主推algorithm的工作因素(迭代次数),包括bcrypt,scrypt和PBKDF2。

我不会以两种不同的方式存储密码哈希值,因为那样的话系统至less和最差的哈希algorithm一样弱。

虽然这个问题已经回答了,但我只想重申,用于散列的盐应该是随机的,不像第一个答案中提到的电子邮件地址。

有关更多解释,请访问http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

最近我有一个讨论,密码哈希与随机位腌制比腌有猜测或已知的盐更安全。 让我们看看:如果存储密码的系统和存储随机盐的系统一样,攻击者可以访问哈希以及盐,那么盐是否是随机的并不重要。 攻击者可以生成预先计算的彩虹表来破解哈希。 这里有趣的部分 – 生成预先计算的表并不是那么简单。 让我们以WPA安全模型为例。 您的WPA密码实际上不会发送到无线接入点。 相反,它是散列与您的SSID(networking名称,如Linksys,Dlink等)。 这是如何工作的一个非常好的解释。 为了从哈希中检索密码,您需要知道密码以及salt(networking名称)。 Wifi教会已经预先计算了哈希表,其中有1000个SSID和大约100万个密码。 所有表格的大小约为40 GB。 正如您可以在他们的网站上阅读的,有人使用了15天的FGPAarrays3天来生成这些表格。 假设受害者使用的SSID为“a387csf3”,密码为“123456”,是否会被这些表破解? 没有! .. 这不可以。 即使密码较弱,表格也没有SSID为a387csf3的散列。 这是随机盐的美丽。 它将威慑在预先计算好的桌子上兴旺的cookies。 它可以阻止一个确定的黑客? 可能不会。 但是使用随机盐确实提供了额外的防御层。 在讨论这个话题的时候,让我们讨论在一个单独的系统中存储随机盐的附加优势。 scheme1:密码哈希存储在系统X上,用于哈希的盐值存储在系统Y上。这些盐值是可猜测的或已知的(例如用户名)scheme#2:密码哈希存储在系统X上,盐值用于散列存储在系统Y上。这些盐值是随机的。 如果系统X已经被攻破,你可以猜测,在单独的系统上使用随机盐有一个巨大的优势(场景#2)。 攻击者需要猜测附加值才能破解哈希。 如果使用32位盐,则每个猜测的密码可能需要2 ^ 32 = 4,294,967,296(约42亿次)的迭代。

从PHP 5.5起,PHP具有用于哈希和validation密码的简单,安全的函数password_hash()和password_verify()

 $password = 'anna'; $hash = password_hash($password, PASSWORD_DEFAULT); $expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20)); password_verify('anna', $hash); //Returns true password_verify('anna', $expensiveHash); //Also returns true password_verify('elsa', $hash); //Returns false 

当使用password_hash() ,它会生成一个随机的salt并将其包含在输出的hash中(以及所使用的成本和algorithm) password_verify()然后读取该hash并确定所使用的salt和encryption方法,并对其进行validation提供的明文密码。

提供PASSWORD_DEFAULT指示PHP使用已安装版本的PHP的默认哈希algorithm。 在未来的版本中,究竟意味着哪种algorithm意图随时间变化,所以它将永远是最强大的可用algorithm之一。

增加成本(默认为10)使哈希更难以暴力,但也意味着生成哈希和validation密码对他们将是更多的工作,为您的服务器的CPU。

请注意,尽pipe默认的哈希algorithm可能会改变,但旧的哈希将继续validation,因为所使用的algorithm存储在哈希中,并且password_verify()在其上进行提取。

我只想指出PHP 5.5包含一个密码散列API ,它提供了一个围绕crypt()的封装。 这个API显着简化了哈希,validation和重新哈希密码哈希的任务。 作者还发布了一个兼容包 (以一个单一的password.php文件的forms,你只require使用),对于那些使用PHP 5.3.7和更高版本,并希望现在就使用它。

它现在只支持BCRYPT,但它的目标是很容易扩展到包含其他密码哈希技术,并且因为技术和成本被存储为哈希的一部分,所以改变你的首选哈希技术/成本不会使当前哈希无效,框架将自动地在validation时使用正确的技术/成本。 如果你没有明确定义你自己的东西,它也处理生成一个“安全”的盐。

该API公开了四个function:

  • password_get_info() – 返回关于给定散列的信息
  • password_hash() – 创build密码哈希
  • password_needs_rehash() – 检查给定的哈希是否与给定的选项匹配。 用于检查散列是否符合您当前的技术/成本scheme,以便在必要时重新散列
  • password_verify() – validation密码是否与散列匹配

目前,这些函数接受PASSWORD_BCRYPT和PASSWORD_DEFAULT密码常量,这两个密码常量在当时是同义词,不同之处在于,当支持更新,更强大的哈希algorithm时,PASSWORD_DEFAULT“可能在更新的PHP版本中发生变化。 在login时使用PASSWORD_DEFAULT和password_needs_rehash()(如果需要的话重新刷新)应该确保你的哈希值对于powershell攻击是合理的弹性,对你来说很less或没有工作。

编辑:我只是意识到,这是在罗伯特·K的答案简要提到。 我会在这里留下这个答案,因为我认为它提供了一些关于它如何工作的信息,以及它为那些不了解安全性的人提供的易用性。

我正在使用Phpass ,它是一个简单的单文件PHP类,几乎可以在每个PHP项目中轻松实现。 另见H。

默认情况下,它使用在Phpass中实现的最强大的可用encryption,它是bcrypt并回退到其他encryption到MD5,以提供向后兼容像WordPress的框架。

返回的散列可以按原样存储在数据库中。 用于生成哈希的示例使用是:

 $t_hasher = new PasswordHash(8, FALSE); $hash = $t_hasher->HashPassword($password); 

要validation密码,可以使用:

 $t_hasher = new PasswordHash(8, FALSE); $check = $t_hasher->CheckPassword($password, $hash); 

要记住的事情

关于PHP的密码encryption已经有很多了,其中大部分都是非常好的build议,但是在开始使用PHP进行密码encryption的过程之前,请确保您已经实现了以下内容或准备好实施。

服务器

PORTS

不pipe你的encryption程序有多好,如果你没有妥善保护运行PHP和DB的服务器,所有的努力都是毫无价值的。 大多数服务器的function相对相同,它们的端口分配为允许您通过ftp或shell远程访问它们。 确保您更改了您所激活的远程连接的默认端口。 通过不这样做,你实际上已经使得攻击者在访问你的系统时less了一步。

用户名

对于世界上的一切都不要使用用户名pipe理员,根或类似的东西。 另外,如果您使用的是基于Unix的系统,则不要使root帐户login可访问,它应该始终为sudo。

密码

你告诉你的用户做好密码,以避免被黑客攻击,做同样的事情。 当你的后门敞开的时候,要经过所有的努力来locking你的前门,这有什么意义呢?

数据库

服务器

理想情况下,您希望您的数据库和应用程序在不同的服 这并不总是可能的,因为成本,但它确实允许一些安全,因为攻击者将不得不经过两个步骤才能完全访问系统。

用户

始终让您的应用程序拥有自己的帐户来访问数据库,只给予它所需的权限。

然后有一个单独的用户帐户不存储在服务器上的任何地方,甚至不在应用程序中。

像永远不要让这根或类似的东西。

密码

遵循与所有良好密码相同的准则。 也不要在同一系统上的任何SERVER或DB帐户上重复使用相同的密码。

PHP

密码

永远不要在你的数据库中存储密码,而是存储哈希和独特的盐,我会解释为什么以后。

HASHING

一种方式哈希!!!!!!!,永远不要以一种可以颠倒的方式哈希密码,哈希应该是一种方式,这意味着你不要扭转它们,并将它们与密码进行比较,而是散列input的密码以同样的方式比较两个哈希。 这意味着即使攻击者访问数据库,他也不知道密码是什么,只是它的结果散列。 这意味着在最糟糕的情况下为您的用户提供更高的安全性。

有很多很好的散列函数( password_hashhash等等),但是你需要select一个好的algorithm来使散列有效。 (bcrypt和类似于它的类似algorithm。)

当哈希速度是关键,越慢抵抗力量攻击。

哈希中最常见的错误之一是哈希不是用户唯一的。 这主要是因为盐不是唯一产生的。

密码在散列之前应始终被腌制。 Salting将一个随机string添加到密码中,所以类似的密码在DB中不会显示相同的密码。 但是,如果盐对每个用户来说都不是唯一的(例如:你使用硬编码的盐),那么你几乎已经使你的盐变得毫无价值。 因为一旦攻击者找出一个密码盐,他就有了所有的盐。

当你创build一个盐时,确保它是唯一的密码,然后将完整的哈希和salt存储在数据库中。 这样做是为了让攻击者在获得访问权限之前,必须单独破解每个salt和hash。 这意味着攻击者需要更多的工作和时间。

用户创build密码

如果用户通过前端创build密码,则意味着必须将其发送到服务器。 这就产生了一个安全问题,因为这意味着未encryption的密码正在被发送到服务器,如果攻击者能够监听并访问你在PHP中的所有安全性是毫无价值的。 总是传输数据安全,这是通过SSL来完成的,但即使SSL并不完美(OpenSSL的Heartbleed缺陷就是一个例子)。

也使用户创build一个安全的密码,这是简单的,应该总是做的,用户将在最后感激。

最后,不pipe你采取什么安全措施都是100%安全的,保护技术越先进,攻击就越发展。 但是,遵循这些步骤将使您的网站更加安全,并且远不如攻击者所希望的。

这里有一个PHP类,它可以很容易地为密码创build一个哈希和盐

http://git.io/mSJqpw

Google表示SHA256可用于PHP。

你一定要用盐。 我build议使用随机字节(而不是限制自己的字符和数字)。 通常情况下,您select的时间越长,越安全,越慢。 我猜,64字节应该没问题。

最后,从mathangular度来说,双哈希没有任何好处。 然而在实践中,这对防止彩虹表攻击是有用的。 换句话说,与使用盐进行哈希处理相比,它没有任何好处,因为在应用程序或服务器上处理的时间要less得多。

我在这里find了关于这个问题的完美话题: https : //crackstation.net/hashing-security.htm ,我想让你从中受益,这里也是提供了防止基于时间攻击的源代码。

 <?php /* * Password hashing with PBKDF2. * Author: havoc AT defuse.ca * www: https://defuse.ca/php-pbkdf2.htm */ // These constants may be changed without breaking existing hashes. define("PBKDF2_HASH_ALGORITHM", "sha256"); define("PBKDF2_ITERATIONS", 1000); define("PBKDF2_SALT_BYTES", 24); define("PBKDF2_HASH_BYTES", 24); define("HASH_SECTIONS", 4); define("HASH_ALGORITHM_INDEX", 0); define("HASH_ITERATION_INDEX", 1); define("HASH_SALT_INDEX", 2); define("HASH_PBKDF2_INDEX", 3); function create_hash($password) { // format: algorithm:iterations:salt:hash $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM)); return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" . $salt . ":" . base64_encode(pbkdf2( PBKDF2_HASH_ALGORITHM, $password, $salt, PBKDF2_ITERATIONS, PBKDF2_HASH_BYTES, true )); } function validate_password($password, $good_hash) { $params = explode(":", $good_hash); if(count($params) < HASH_SECTIONS) return false; $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]); return slow_equals( $pbkdf2, pbkdf2( $params[HASH_ALGORITHM_INDEX], $password, $params[HASH_SALT_INDEX], (int)$params[HASH_ITERATION_INDEX], strlen($pbkdf2), true ) ); } // Compares two strings $a and $b in length-constant time. function slow_equals($a, $b) { $diff = strlen($a) ^ strlen($b); for($i = 0; $i < strlen($a) && $i < strlen($b); $i++) { $diff |= ord($a[$i]) ^ ord($b[$i]); } return $diff === 0; } /* * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt * $algorithm - The hash algorithm to use. Recommended: SHA256 * $password - The password. * $salt - A salt that is unique to the password. * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000. * $key_length - The length of the derived key in bytes. * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise. * Returns: A $key_length-byte key derived from the password and salt. * * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt * * This implementation of PBKDF2 was originally created by https://defuse.ca * With improvements by http://www.variations-of-shadow.com */ function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) { $algorithm = strtolower($algorithm); if(!in_array($algorithm, hash_algos(), true)) die('PBKDF2 ERROR: Invalid hash algorithm.'); if($count <= 0 || $key_length <= 0) die('PBKDF2 ERROR: Invalid parameters.'); $hash_length = strlen(hash($algorithm, "", true)); $block_count = ceil($key_length / $hash_length); $output = ""; for($i = 1; $i <= $block_count; $i++) { // $i encoded as 4 bytes, big endian. $last = $salt . pack("N", $i); // first iteration $last = $xorsum = hash_hmac($algorithm, $last, $password, true); // perform the other $count - 1 iterations for ($j = 1; $j < $count; $j++) { $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true)); } $output .= $xorsum; } if($raw_output) return substr($output, 0, $key_length); else return bin2hex(substr($output, 0, $key_length)); } ?> 

I usually use SHA1 and salt with the user ID (or some other user-specific piece of information), and sometimes I additionally use a constant salt (so I have 2 parts to the salt).

SHA1 is now also considered somewhat compromised, but to a far lesser degree than MD5. By using a salt (any salt), you're preventing the use of a generic rainbow table to attack your hashes (some people have even had success using Google as a sort of rainbow table by searching for the hash). An attacker could conceivably generate a rainbow table using your salt, so that's why you should include a user-specific salt. That way, they will have to generate a rainbow table for each and every record in your system, not just one for your entire system! With that type of salting, even MD5 is decently secure.

SHA1 and a salt should suffice (depending, naturally, on whether you are coding something for Fort Knox or a login system for your shopping list) for the foreseeable future. If SHA1 isn't good enough for you, use SHA256 .

The idea of a salt is to throw the hashing results off balance, so to say. It is known, for example, that the MD5-hash of an empty string is d41d8cd98f00b204e9800998ecf8427e . So, if someone with good enough a memory would see that hash and know that it's the hash of an empty string. But if the string is salted (say, with the string " MY_PERSONAL_SALT "), the hash for the 'empty string' (ie " MY_PERSONAL_SALT ") becomes aeac2612626724592271634fb14d3ea6 , hence non-obvious to backtrace. What I'm trying to say, that it's better to use any salt, than not to. Therefore, it's not too much of an importance to know which salt to use.

There are actually websites that do just this – you can feed it a (md5) hash, and it spits out a known plaintext that generates that particular hash. If you would get access to a database that stores plain md5-hashes, it would be trivial for you to enter the hash for the admin to such a service, and log in. But, if the passwords were salted, such a service would become ineffective.

Also, double-hashing is generally regarded as bad method, because it diminishes the result space. All popular hashes are fixed-length. Thus, you can have only a finite values of this fixed length, and the results become less varied. This could be regarded as another form of salting, but I wouldn't recommend it.

ok in the fitsy we need salt salt must be unique so let generate it

  /** * Generating string * @param $size * @return string */ function Uniwur_string($size){ $text = md5(uniqid(rand(), TRUE)); RETURN substr($text, 0, $size); } 

also we need the hash I`m using sha512 it is the best and it is in php

  /** * Hashing string * @param $string * @return string */ function hash($string){ return hash('sha512', $string); } 

so now we can use this functions to generate safe password

 // generating unique password $password = Uniwur_string(20); // or you can add manual password // generating 32 character salt $salt = Uniwur_string(32); // now we can manipulate this informations // hashin salt for safe $hash_salt = hash($salt); // hashing password $hash_psw = hash($password.$hash_salt); 

now we need to save in database our $hash_psw variable value and $salt variable

and for authorize we will use same steps…

it is the best way to safe our clients passwords…

Ps for last 2 steps you can use your own algorithm… but be sure that you can generate this hashed password in the future when you need to authorize user…