Reputation: 48899
Excuse me for this very odd question. I understand the purpose of base64 encoding for transmitting data (i.e. MIME's Base64 encoding), but I don't know if I need to base64 encode my salts.
I wrote an utility class (a base abstract class indeed):
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);
}
}
A real implementation class would be:
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));
}
}
The key part is the salt generation, which will be embedded in the password: do I need base64_encode
for any reason (storing), assuming that it will be never sent over the wire?
Upvotes: 1
Views: 6479
Reputation: 24071
Each hash algorithm expects a salt in a given alphabet, that means using base64_encode()
can be the right thing, but often it does either not use the full alphabet or returns characters that are not in this alphabet.
Take BCrypt for example, this is a good hash algorithm for passwords (SHA-512 is not appropriate because it is too fast), it accepts all characters of a base64-encoded string except the '+' character. On the other side it accepts '.' characters that are not part of a base64-encoded string.
PHP 5.5 will have the functions password_hash()
and password_verify()
ready, to make the usage of BCrypt easier, i really can recommend them. There is also a compatibility pack available for older PHP versions, on line 121 you can see that base64_encode()
is indeed used, but afterwards all invalid '+' characters are replaced with allowed '.' characters:
Encoding a salt for BCrypt:
$salt = str_replace('+', '.', base64_encode($buffer));
Upvotes: 3