- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我一直在研究散列/加密密码并将其存储在数据库中的正确方法。我知道 Salt 和 Hashing,所以我环顾四周,发现 PBKDF2 似乎是一个不错的选择。所以我找到了this website这提供了一个很好的教程以及 PBKDF2 的 PHP 改编版(这是我在我的网站上使用的)。
因此,我已将我的网站设置为使用这些函数来生成/创建密码,但正如您在以下代码中看到的那样:
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
)); }
salt 在 create_hash 函数中生成,并存储在最终看起来像 sha256:1000:salt:hashed_password 的结果哈希中。这是我必须存储在我的数据库中的内容,并且由于盐包含在生成的哈希中,所以我不需要将它添加到我的数据库中。然而,在生成了一些测试用户之后,我想知道在数据库中的哈希密码中包含 PBKDF2 设置是否真的是一件好事。他们以我的新手自认为是黑客的方式,在破解我的数据库之后,会看到这些一堆 sha256:1000:salt:password 东西,并弄清楚每个部分代表什么,这对他的尝试有很大帮助,不?
因此我对其进行了一些修改,使其具有生成并存储在数据库中的外部盐,并在通过 PBKDF2 运行之前将盐包含在密码中。然后我做同样的事情来比较给定的密码和我在数据库中的登录密码,并且它有效。我唯一担心的是,使用 128 位盐后,生成的密码哈希长度仅为 50 个字符,这对我来说似乎不正确。
这是我当前的代码:
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 10000);
define("PBKDF2_SALT_BYTES", 128);
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, $salt)
{
// format: salthash
return
base64_encode(pbkdf2(
PBKDF2_HASH_ALGORITHM,
$password,
$salt,
PBKDF2_ITERATIONS,
PBKDF2_HASH_BYTES,
true
));
}
function validate_password($password, $salt, $good_hash)
{
$pbkdf2 = base64_decode($good_hash);
return slow_equals(
$pbkdf2,
pbkdf2(
PBKDF2_HASH_ALGORITHM,
$password,
$salt,
PBKDF2_ITERATIONS,
PBKDF2_HASH_BYTES,
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;
}
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));
}
我对这种密码保存格式的担忧是否有意义?还是它只是等同于同一件事,因为通过在我的数据库中加入我的盐,一旦它被破解,黑客仍然可以暴力破解?
谢谢,很抱歉问了这么长的问题。
最佳答案
My only concern is that a with 128bit salt, the resulting password hash is barely 50 characters long, that doesn't seem right to me.
生成的散列的大小与盐的大小、密码和迭代次数完全无关。无论输入如何,现代安全哈希算法(如 sha256)的输出总是相同的长度。零长度输入与 25TB 输入具有相同长度的输出。
Or will it just amount to the same thing anyway, since by having my salt in my database, once it's cracked, the hacker can still brute-force his way through?
通过将 salt 分成两部分,您会增加代码的复杂性(通常是一件坏事)。根据您储存盐 block 的方式,在某些情况下您可能会受益匪浅。例如,如果静态盐片段存储在数据库外部,则数据库的转储不会为攻击者提供足够的信息来对数据库中的密码哈希执行离线攻击。
如果盐碎片彼此分开存储,则 yield 是少量的纵深防御。它是否超过复杂性成本是一个判断电话,但我认为很有可能将时间花在寻找 XSS 和 SQL 注入(inject)漏洞上(攻击者通常获取数据库的方式)上面提到的转储),并使用 SSL 和证书或强密码保护系统各个组件之间的连接。
关于php - 如何正确存储 PBKDF2 密码哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11734495/
我正在尝试 grep conf 文件中所有不以 开头的有效行 哈希(或) 任意数量的空格(0 个或多个)和一个散列 下面的正则表达式似乎不起作用。 grep ^[^[[:blank:]]*#] /op
我正在使用哈希通过 URL 发送 protected 电子邮件以激活帐户 Hash::make($data["email"]); 但是哈希结果是 %242y%2410%24xaiB/eO6knk8sL
我是 Perl 的新手,正在尝试从文本文件创建散列。我有一个代码外部的文本文件,旨在供其他人编辑。前提是他们应该熟悉 Perl 并且知道在哪里编辑。文本文件本质上包含几个散列的散列,具有正确的语法、缩
我一直在阅读 perl 文档,但我不太了解哈希。我正在尝试查找哈希键是否存在,如果存在,则比较其值。让我感到困惑的是,我的搜索结果表明您可以通过 if (exists $files{$key}) 找到
我遇到了数字对映射到其他数字对的问题。例如,(1,2)->(12,97)。有些对可能映射到多个其他对,所以我真正需要的是将一对映射到列表列表的能力,例如 (1,2)->((12,97),(4,1))。
我见过的所有 Mustache 文档和示例都展示了如何使用散列来填充模板。我有兴趣去另一个方向。 EG,如果我有这个: Hello {{name}} mustache 能否生成这个(伪代码): tag
我正在尝试使用此公式创建密码摘要以获取以下变量,但我的代码不匹配。不确定我做错了什么,但当我需要帮助时我会承认。希望有人在那里可以提供帮助。 文档中的公式:Base64(SHA1(NONCE + TI
我希望遍历我传递给定路径的这些数据结构(基本上是目录结构)。 目标是列出根/基本路径,然后列出所有子 path s 如果它们存在并且对于每个子 path存在,列出 file从那个子路径。 我知道这可能
我希望有一个包含对子函数的引用的散列,我可以在其中根据用户定义的变量调用这些函数,我将尝试给出我正在尝试做的事情的简化示例。 my %colors = ( vim => setup_vim()
我注意到,在使用 vim 将它们复制粘贴到文件中后尝试生成一些散列时,散列不是它应该的样子。打开和写出文件时相同。与 nano 的行为相同,所以一定有我遗漏的地方。 $ echo -n "foo"
数组和散列作为状态变量存在限制。从 Perl 5.10 开始,我们无法在列表上下文中初始化它们: 所以 state @array = qw(a b c); #Error! 为什么会这样?为什么这是不允
在端口 80 上使用 varnish 5.1 的多网站设置中,我不想缓存所有域。 这在 vcl_recv 中很容易完成。 if ( req.http.Host == "cache.this.domai
基本上,缓存破坏文件上的哈希不会更新。 class S3PipelineStorage(PipelineMixin, CachedFilesMixin, S3BotoStorage): pa
eclipse dart插件在“变量” View 中显示如下内容: 在“值”列中可见的“id”是什么意思? “id”是唯一的吗?在调试期间,如何确定两个实例是否相同?我是否需要在所有类中重写toStr
如何将Powershell中的命令行参数读入数组?就像是 myprogram -file file1 -file file2 -file file3 然后我有一个数组 [file1,file2,fil
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
例如,我有一个包含 5 个元素的哈希: my_hash = {a: 'qwe', b: 'zcx', c: 'dss', d: 'ccc', e: 'www' } 我的目标是每次循环哈希时都返回,但没
我在这里看到了令人作呕的类似问题,但没有一个能具体回答我自己的问题。 我正在尝试以编程方式创建哈希的哈希。我的问题代码如下: my %this_hash = (); if ($user_hash{$u
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
这个问题已经有答案了: Java - how to convert letters in a string to a number? (9 个回答) 已关闭 7 年前。 我需要一种简短的方法将字符串转
我是一名优秀的程序员,十分优秀!