2

I am storing passwords on a SQL database, using PHP and planning to use bcrypt.

I was doing some research to find what types and size I should use to store the hash and salt in my database.

Based on the great answer to this question, it seems that bcrypt sometimes outputs different sized hashes, maybe as large as CHAR(76) or BINARY(60). But I don't understand when and why.

That question provides a link which says that using the $2$ scheme produces 59 bytes, and $2a$ produces 60 bytes. However today's documentation for php's crypt recommends using $2y$ over $2a$, for some reason due to high bit attacks, or something. Anyway, I would like to use $2y$ as it is recommended, however there is no indication of the size of the has it will output.

What should the size of my fields in the database be?

Also, is there any practical difference between CHAR and BINARY in this sort of application?

Community
  • 1
  • 1
Bingo
  • 3,785
  • 6
  • 23
  • 27
  • possible duplicate of [Storing a hashed password (Bcrypt) in a Database - type/length of column?](http://stackoverflow.com/questions/5881169/storing-a-hashed-password-bcrypt-in-a-database-type-length-of-column) – Andre D Oct 04 '13 at 23:55

2 Answers2

1
  1. Hash: CHAR(60)
  2. Salt: CHAR(22)

This can be found experimentally:

<?php
    $salt1 = "FotZoGZruCl8ugk0Tvl4g";
    $salt2 = "FotZoGZruCl8ugk0Tvl4g9";
    $salt3 = "FotZoGZruCl8ugk0Tvl4g9a";

    print 'Salt 1 (stlen = ' . strlen($salt1) . '): ' . $salt1 . '<br />';
    print 'Salt 2 (stlen = ' . strlen($salt2) . '): ' . $salt2 . '<br />';
    print 'Salt 3 (stlen = ' . strlen($salt3) . '): ' . $salt3 . '<br />';

    $hash1 = crypt('password1', '$2y$07$' . $salt1);
    $hash2 = crypt('password1', '$2y$07$' . $salt2);
    $hash3 = crypt('password1', '$2y$07$' . $salt3);

    print 'Hash 1 (strlen = ' . strlen($hash1) . '): ' . $hash1 . '<br />';
    print 'Hash 2 (strlen = ' . strlen($hash2) . '): ' . $hash2 . '<br />';
    print 'Hash 3 (strlen = ' . strlen($hash3) . '): ' . $hash3 . '<br />';
?>

The output will be:

Salt 1 (stlen = 21): FotZoGZruCl8ugk0Tvl4g
Salt 2 (stlen = 22): FotZoGZruCl8ugk0Tvl4g9
Salt 3 (stlen = 23): FotZoGZruCl8ugk0Tvl4g9a
Hash 1 (strlen = 60): $2y$07$FotZoGZruCl8ugk0Tvl4g.pXg.UBUUwuj14Ur1d.z/tMLqGPxQLBW
Hash 2 (strlen = 60): $2y$07$FotZoGZruCl8ugk0Tvl4guNd47GUslNQPXiel70rI0yvffP7iPSHe
Hash 3 (strlen = 60): $2y$07$FotZoGZruCl8ugk0Tvl4guNd47GUslNQPXiel70rI0yvffP7iPSHe

You will notice here than if you add to the salt beyond 22 characters, the hash will remain unchanged. That is, crypt will truncate the salt down to 22 characters before performing the hash.

FYI, random salt generation:

$salt = substr(strtr(base64_encode(mcrypt_create_iv(17, MCRYPT_DEV_URANDOM)), "=+", "./"), 0, 22);

EDIT: Also, the format of the salt/hash is base 64. That is using a-z, A-Z, 0-9, '.' and '/' as digits, each digit representing a value from 0 to 63... so using CHAR in the database is fine with respect to BINARY because you can represent all of those digits with CHAR.

Bingo
  • 3,785
  • 6
  • 23
  • 27
0

It'll be the same size - 60 characters. (The only difference between $2$ and $2a$ is that the former is one less character. The actual hash part is the same size.)

Ry-
  • 218,210
  • 55
  • 464
  • 476