我想知道此功能(部分取自〜2岁的phpBB版本)是否足够好。
如果没有,为什么?
以及您将如何更改它(使现有用户无缝过渡)?
hash_pwd()的结果将保存在数据库中。
function hash_pwd($password)
{
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$random_state = $this->unique_id();
$random = '';
$count = 6;
if (($fh = @fopen('/dev/urandom', 'rb')))
{
$random = fread($fh, $count);
fclose($fh);
}
if (strlen($random) < $count)
{
$random = '';
for ($i = 0; $i < $count; $i += 16)
{
$random_state = md5($this->unique_id() . $random_state);
$random .= pack('H*', md5($random_state));
}
$random = substr($random, 0, $count);
}
$hash = $this->_hash_crypt_private($password, $this->_hash_gensalt_private($random, $itoa64), $itoa64);
if (strlen($hash) == 34)
{
return $hash;
}
return false;
}
function unique_id()
{
$val = microtime();
$val = md5($val);
return substr($val, 4, 16);
}
function _hash_crypt_private($password, $setting, &$itoa64)
{
$output = '*';
// Check for correct hash
if (substr($setting, 0, 3) != '$H$')
{
return $output;
}
$count_log2 = strpos($itoa64, $setting[3]);
if ($count_log2 < 7 || $count_log2 > 30)
{
return $output;
}
$count = 1 << $count_log2;
$salt = substr($setting, 4, 8);
if (strlen($salt) != 8)
{
return $output;
}
/**
* We're kind of forced to use MD5 here since it's the only
* cryptographic primitive available in all versions of PHP
* currently in use. To implement our own low-level crypto
* in PHP would result in much worse performance and
* consequently in lower iteration counts and hashes that are
* quicker to crack (by non-PHP code).
*/
if (PHP_VERSION >= 5)
{
$hash = md5($salt . $password, true);
do
{
$hash = md5($hash . $password, true);
}
while (--$count);
}
else
{
$hash = pack('H*', md5($salt . $password));
do
{
$hash = pack('H*', md5($hash . $password));
}
while (--$count);
}
$output = substr($setting, 0, 12);
$output .= $this->_hash_encode64($hash, 16, $itoa64);
return $output;
}
function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6)
{
if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
{
$iteration_count_log2 = 8;
}
$output = '$H$';
$output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
$output .= $this->_hash_encode64($input, 6, $itoa64);
return $output;
}
function _hash_encode64($input, $count, &$itoa64)
{
$output = '';
$i = 0;
do
{
$value = ord($input[$i++]);
$output .= $itoa64[$value & 0x3f];
if ($i < $count)
{
$value |= ord($input[$i]) << 8;
}
$output .= $itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count)
{
break;
}
if ($i < $count)
{
$value |= ord($input[$i]) << 16;
}
$output .= $itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count)
{
break;
}
$output .= $itoa64[($value >> 18) & 0x3f];
}
while ($i < $count);
return $output;
}
最佳答案
您提供的代码是PHPASS的端口,特别是“便携式”算法。注意portable的限定条件。如果您将phpass作为第二个构造函数参数传递,则这仅适用于true库。从此以后,此答案中的phpass仅将引用引用可移植算法,而不是库本身。如果您未显式指定portable,则默认情况下该库将执行bcrypt。
PHPBB团队并没有自己开发(很好),而是直接从phpass移植了(可争论)。
我们应该在这里提出几个问题:
不好吗?
简短的答案是“不,这还不错”。它提供了很好的安全性。如果您现在对此有代码,那么我就不会着急将其删除。适用于大多数用途。但是话虽如此,如果您开始一个我不会选择的新项目,那么还有更好的选择。
有哪些弱点?
pbkdf2 :phpass算法使用 hash() ,而pbkdf2()使用 hash_hmac() 。现在,HMAC内部为每个调用运行2个散列,但是PHP实现仅花费对hash()的单个调用执行的1.6倍(C不好吗?)。因此,我们在hash_hmac执行2个散列所需的时间中,有62%的时间从hash()获得2个散列。pbkdf2将比phpass算法多运行约37.5%的散列。给定时间内更多的哈希==好,因为它导致执行更多的计算。pbkdf2)时,37.5%大约比phpass强md5。但是pbkdf2也可以采用更强大的基元。因此,我们可以将pbkdf2与sha512结合使用,以获得比phpass算法非常重要的优势(主要是因为sha512是比md5运算量更大的更难算法)。pbkdf2不仅可以在相同的时间内生成更多的计算,而且还可以生成更困难的计算。pbkdf2绝对比phpass“更强”。 bcrypt:比较起来很难。但是,让我们看一下它的表面。 phpass使用md5和PHP中的循环。 pbkdf2使用任何原语(在C中)和PHP中的循环。 bcrypt在C语言中全部使用自定义算法(这意味着它与任何可用的散列算法都不同)。因此,最棒的是,bcrypt仅对算法全部在C中这一事实具有明显的优势。这允许每单位时间进行更多的“计算”。从而使其成为一种更有效的慢速算法(在给定的运行时中进行更多的计算)。bcrypt的更强本质的一个示例是bcrypt使用的内部状态比正常的哈希函数大得多的事实。 SHA512使用512位内部状态针对1024位块进行计算。 bcrypt使用大约32kb的内部状态来针对576位的单个块进行计算。 bcrypt的内部状态比SHA512(以及md5和phpass)大得多的事实,在一定程度上说明了bcrypt的更强本质。 bcrypt更强,请查看Slides from Password13 (PDF),它启动了25个GPU集群来破解密码哈希。以下是相关结果:md5($password)sha1($password)md5crypt(与phpass非常相似,费用为10):bcrypt,费用为5a-zA-Z0-9~`!@#$%^&*()_+-={}|[]\:";'<>,.?/
bcrypt。如果现在正在生产中有phpass或pbkdf2,则可能要升级,但这并不是明确的“您非常脆弱”。
关于php - 这在PHP中是一个很好的哈希密码功能吗?如果没有,为什么不呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16042128/
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案