1

对不起这个非常奇怪的问题。我了解 base64 编码用于传输数据的目的(即 MIME 的 Base64 编码),但我不知道是否需要对我的盐进行 base64 编码。

我写了一个实用程序类(确实是一个基本抽象类):

use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;

abstract class AbstractCryptPasswordEncoder extends BasePasswordEncoder
{
    /**
     * @return string
     */
    protected abstract function getSaltPrefix();

    /**
     * @return string
     */
    protected abstract function getSalt();

    /**
     * {@inheritdoc}
     */
    public function encodePassword($raw, $salt = null)
    {
        return crypt($raw, $this->getSaltPrefix().$this->getSalt());
    }

    /**
     * {@inheritdoc}
     */
    public function isPasswordValid($encoded, $raw, $salt = null)
    {
        return $encoded === crypt($raw, $encoded);
    }
}

一个真正的实现类是:

class Sha512CryptPasswordEncoder extends AbstractCryptPasswordEncoder
{
    /**
     * @var string
     */
    private $rounds;

    /**
     * @param null|int $rounds The number of hashing loops
     */
    public function __construct($rounds = null)
    {
        $this->rounds = $rounds;
    }

    /**
     * {@inheritdoc}
     */
    protected  function getSaltPrefix()
    {
        return sprintf('$6$%s', $this->rounds ? "rounds={$this->rounds}$" : '');
    }

    /**
     * {@inheritdoc}
     */
    protected function getSalt()
    {
        return base64_encode(openssl_random_pseudo_bytes(12));
    }
}

关键部分是盐生成,它将嵌入密码中:base64_encode假设它永远不会通过网络发送,我是否需要任何原因(存储)?

4

2 回答 2

3

每个哈希算法都需要给定字母表中的盐,这意味着使用base64_encode()可能是正确的,但通常它要么不使用完整的字母表,要么返回不在此字母表中的字符。

以 BCrypt 为例,这是一个很好的密码哈希算法(SHA-512 不适合,因为它太快了),它接受 base64 编码字符串的所有字符,除了 '+' 字符。另一方面,它接受'。不属于 base64 编码字符串的字符。

PHP 5.5 将具有功能password_hash()password_verify()准备,使 BCrypt 的使用更容易,我真的可以推荐它们。还有一个兼容包可用于较旧的 PHP 版本,在第 121 行你可以看到base64_encode()确实使用了它,但之后所有无效的 '+' 字符都被替换为允许的 '.' 人物:

为 BCrypt 编码盐:

$salt = str_replace('+', '.', base64_encode($buffer));
于 2013-02-01T15:13:12.910 回答
1

BASE64用于将二进制数据编码为文本表示。它允许使用文本通道传输二进制数据。如果您想在 DB 中存储散列密码,则不必对其进行编码 - 它已经是文本格式。

于 2013-02-01T14:18:34.540 回答