C中的盐渍sha512,无法与Symfony2的FOSUserBundle同步

时间:2013-08-17 13:42:27

标签: c symfony fosuserbundle sha512

我的发展分为两个部分:

  • 网站,使用FOSUserBundle的Symfony应用程序,使用SHA512加密密码,以及盐。
  • 一个用C语言编写的认证模块,它应该能够在给出盐和密文密码后再现SHA512盐渍哈希。

有关我的环境的一些信息

  • 我正在使用Linux Ubuntu 12.04。
  • ldd --version回答 EGLIBC 2.15-0ubuntu10.4 2.15 (也许我需要2.7?但在正确升级包时,apt-get是真正的PAIN。)
  • crypt.h标题文件提及 @(#)crypt.h 1.5 12/20/96

问题本身

我的问题出现在身份验证模块中:我无法获得与Symfony的FOSUserBundle生成的哈希相同的哈希值。这是我的例子:

  • Symfony使用的密码salt为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存储密码的方式吗?

1 个答案:

答案 0 :(得分:4)

不是真正的答案,但我猜你没有研究过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文件中调整)。

您还可以查看salt和密码合并在一起的位置。这解释了其他stackoverflow的答案。

使用symfony命令从symfony控制台运行此编码算法进行测试将是微不足道的。之后只是调整输入或调整C代码直到结果匹配的问题。

如果你很幸运,那么你所要做的就是添加迭代循环。