我的开发分为两个部分:
- 网站、使用 FOSUserBundle 的 Symfony 应用程序(使用 SHA512 加密密码)和盐。
- 一个用 C 语言编程的身份验证模块,一旦给出盐和明文密码,它应该能够重现 SHA512 加盐哈希。
有关我的环境的一些信息
- 我使用的是 Linux Ubuntu 12.04。
ldd --version
回答 EGLIBC 2.15-0ubuntu10.4 2.15 (也许我需要 2.7?但是apt-get
是一个真正的痛苦当涉及到正确升级软件包时)。crypt.h
头文件提到 @(#)crypt.h 1.5 12/20/96
问题本身
我的问题出现在身份验证模块中:我无法获得与 Symfony 的 FOSUserBundle 生成的哈希值相同的哈希值。这是我的例子:
- Symfony 使用的密码盐是
bcccy6eiye8kg44scw0wk8g4g0wc0sk
。 - 密码本身是
test
利用这些信息,Symfony 存储最终的哈希值:
fH5vVoACB4e8h1GX81n+aYiRkSWxeu4TmDibNChtLNZS3jmFKBZijGCXcfzCSJFg+YvNthxefHOBk65m/U+3OA==
现在,在我的 C 身份验证模块中,我运行这段代码(包含 crypt.h
):
char* password = "test";
char* salt = "$6$bcccy6eiye8kg44scw0wk8g4g0wc0sk";
char* hash = malloc(256);
memset(hash, 0, 256);
encode64(crypt(password, salt), hash, strlen(password));
fprintf(stdout, "%s\n", hash);
(这是我的 Base64 编码器: http://libremail.tuxfamily.org/sources/base64-c.htm )
这输出...
JDYkYg==
这与我的 Symfony2 哈希完全不同。
浏览 Stack Overflow,我发现这个问题 ( Symfony2 (FOSUserBundle) SHA512 hash doesn't match C# SHA512 hash ) 是由遇到同样问题的人写的(尽管使用 C#)。所以我决定运行这个测试...
char* password = "test{bcccy6eiye8kg44scw0wk8g4g0wc0sk}";
char* salt = "$6$bcccy6eiye8kg44scw0wk8g4g0wc0sk"; // I tried without salt, or with "$6$" as well.
char* hash = malloc(256);
memset(hash, 0, 256);
encode64(crypt(password, salt), hash, strlen(password));
fprintf(stdout, "%s\n", hash);
当然,这是一次彻底的失败,我得到了:
JDYkYmNjY3k2ZWl5ZThrZzQ0cyRycmN6TnpJUXFOYU1VRlZvMA==
我尝试过以各种方式混合密码和盐,但我永远无法在身份验证模块中获取 Symfony 的盐。我在路上错过了什么吗?我是否误解了 Symfony 的 FOSUserBundle 存储密码的方式?
最佳答案
这并不是一个真正的答案,但我猜你还没有详细研究过 Symfony 如何对密码进行编码?编码过程隐藏在编码器对象中。对于 SHA512,我们使用:
namespace Symfony\Component\Security\Core\Encoder;
class MessageDigestPasswordEncoder extends BasePasswordEncoder
{
/**
* Constructor.
*
* @param string $algorithm The digest algorithm to use
* @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash
* @param integer $iterations The number of iterations to use to stretch the password hash
*/
public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 5000)
{
$this->algorithm = $algorithm;
$this->encodeHashAsBase64 = $encodeHashAsBase64;
$this->iterations = $iterations;
}
public function encodePassword($raw, $salt)
{
if (!in_array($this->algorithm, hash_algos(), true)) {
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
}
$salted = $this->mergePasswordAndSalt($raw, $salt);
$digest = hash($this->algorithm, $salted, true);
// "stretch" hash
for ($i = 1; $i < $this->iterations; $i++) {
$digest = hash($this->algorithm, $digest.$salted, true);
}
return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
}
public function isPasswordValid($encoded, $raw, $salt)
{
return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
}
protected function mergePasswordAndSalt($password, $salt)
{
if (empty($salt)) {
return $password;
}
if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) {
throw new \InvalidArgumentException('Cannot use { or } in salt.');
}
return $password.'{'.$salt.'}';
}
正如您所看到的,一个迫在眉睫的问题是默认情况下散列会重复 5000 次。这(以及其他输入都可以在 app/config/security.yml 文件中调整)。
您还可以看到盐和密码合并在一起的位置。这解释了其他 stackoverflow 答案。
创建一个 symfony 命令来从 symfony 控制台运行此编码算法进行测试是很简单的。之后,只需调整输入或调整 C 代码直到结果匹配即可。
如果你幸运的话,那么你所要做的就是添加迭代循环。
关于c - C 中的 Salted sha512,无法与 Symfony2 的 FOSUserBundle 同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18289472/