2013-02-01 91 views
1

对不起,这个很奇怪的问题。我理解用于传输数据的base64编码(即MIME的Base64编码)的目的,但我不知道是否需要对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出于任何原因(存储),假设它永远不会通过电线发送?

+0

参考这个问题:http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords但是,没有 - 你不应该在哈希密码上使用base64。 –

回答

3

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

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

PHP 5.5将准备好函数password_hash()password_verify(),使BCrypt的使用更容易,我真的可以推荐它们。还有一个compatibility pack可用于较老的PHP版本,在第121行中,您可以看到base64_encode()确实被使用,但之后所有无效的“+”字符都被替换为允许的'。'。人物:

编码盐为BCrypt:

$salt = str_replace('+', '.', base64_encode($buffer)); 
+0

+1为一个很好的答案。关于兼容性包的一点不完全清楚,因此为了其他人的利益,兼容包是一个可下载的库,它为PHP 5.3或5.4的用户实现了PHP5.5'password_xxx()'函数。这意味着**任何目前支持的PHP版本的所有用户都可以使用新的官方PHP密码API **。 – SDC

+0

@SDC - 感谢您的评论,我试图让它更清楚一点。 – martinstoeckli

+0

优秀的答案,+1。虽然河豚盐的要求对我来说很清楚(base64编码随机字节,'+'替换),但它仍不清楚sha512盐的要求:原始字节?一些字母表? – gremo

1

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