1

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?

gremo
  • 47,186
  • 75
  • 257
  • 421
  • Refer to this question: http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords But no - you shouldn't use base64 on hashed passwords. – Vlad Preda Feb 01 '13 at 14:19

2 Answers2

3

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));
martinstoeckli
  • 23,430
  • 6
  • 56
  • 87
  • +1 for a good answer. The bit about the compatiblity pack wasn't totally clear, so for the benefit of others, the compatibility pack is a downloadable library that implements the PHP5.5 `password_xxx()` functions for users of PHP 5.3 or 5.4. Which means that **all users of any currently supported PHP version can use the new official PHP password API**. – SDC Feb 01 '13 at 15:38
  • @SDC - Thanks for the comment, i tried to make it a bit more clear. – martinstoeckli Feb 01 '13 at 15:43
  • Excellent answer, +1. While the blowfish salt requirements are very clear to me (base64 encode random bytes, '+' replacement) it's still not clear the sha512 salt requirements: raw bytes? Some alphabet? – gremo Feb 01 '13 at 15:52
  • @Gremo - Just had a look at the PHP source code and didn't find any restrictions about the SHA-512 aphabet of the salt. The code uses `strcspn()` to find the terminating '$' of the salt, that means the salt should not contain null characters and no '$' character of course. So you cannot use a raw byte salt and no unicode characters (they normally contain a null byte). I cannot tell for sure, that i got it all right (i'm not a C crack), so maybe it's best to use the same alphabet as the other algorithms like BCrypt, just to be on the safe side. – martinstoeckli Feb 01 '13 at 21:24
1

BASE64 is used to encode binary data into text representation. It allow to transfer binary data using text channels. If you want to store hashed password in DB you don't have to encode it - it is already in text format.

ziemo
  • 73
  • 4