290

I'm going to run SHA256 on a password + salt, but I don't know how long to make my VARCHAR when setting up the MySQL database. What is a good length?

kenorb
  • 137,499
  • 74
  • 643
  • 694
Tony Stark
  • 23,318
  • 38
  • 93
  • 112
  • 13
    Before anyone reading this decides to follow this advice and use `SHA-*` to hash passwords, [PLEASE read this first](https://security.stackexchange.com/questions/16354/whats-the-advantage-of-using-pbkdf2-vs-sha256-to-generate-an-aes-encryption-key). – c00000fd May 10 '17 at 05:31
  • 3
    Unless you’re using SHA-256 on passwords, which you shouldn’t do, the hashes have a length of 256 bits, or 64 hexadecimal characters, or 43 alphanumeric characters, or 32 bytes. – caw Nov 20 '19 at 16:01
  • @c00000fd: I'm not sure that the link is particularly relevant. The OP specifically wants to use a 'password+salt'. If the salt is 16 random characters, for example, then it doesn't matter that SHA-256 is 'fast', and dictionary attacks are then impossible. See the gnu docs for `crypt` for example code. SHA-x is fine for passphrases, as long as you know what you're doing. – EML Sep 13 '21 at 10:36

5 Answers5

412

A sha256 is 256 bits long -- as its name indicates.

Since sha256 returns a hexadecimal representation, 4 bits are enough to encode each character (instead of 8, like for ASCII), so 256 bits would represent 64 hex characters, therefore you need a varchar(64), or even a char(64), as the length is always the same, not varying at all.

And the demo :

$hash = hash('sha256', 'hello, world!');
var_dump($hash);

Will give you :

$ php temp.php
string(64) "68e656b251e67e8358bef8483ab0d51c6619f3e7a1a9f0e75838d41ff368f728"

i.e. a string with 64 characters.

mehov
  • 4,178
  • 3
  • 40
  • 55
Pascal MARTIN
  • 385,748
  • 76
  • 642
  • 654
  • 7
    can we use char(64) as the primary key or will binary(32) be better for that? (access_token) – frankish Sep 15 '13 at 10:18
  • 4
    If you think you might want to block a user in the future, then I suggest using `varchar(65)` for a leading `!`... just saying. – Manatax Mar 09 '14 at 21:42
  • 128
    ...or just add a column 'blocked' ? – Stijn de Witt Oct 10 '14 at 19:57
  • 6
    As you want to have a different salt for each password you have to store this next to the hash. For this you can use an extra field or pre-/append it to the hash, so you will need more than 64 chars – Patrick Cornelissen Apr 24 '15 at 17:21
  • 4
    you can use this select statement to test it: `SELECT length(to_base64(unhex(sha2('say hello to my little friend',256))))` , it is always 44 whatever the length of original string is. – DrAhmedJava Apr 09 '17 at 13:57
  • 1
    If you must use text, base64 encode to save some space, or better yet use a binary field – jjxtra Jul 29 '20 at 14:46
  • PLEASE DON'T JUST SHA-256 A PASSWORD w/ or w/o SALT. Use PBKDF2, bcrypt, or scrypt. If your password database is ever leaked, these are resistant to brute-force reversing. https://medium.com/@kasunpdh/how-to-store-passwords-securely-with-pbkdf2-204487f14e84 – jsears Mar 31 '21 at 19:40
  • @PatrickCornelissen: add the random salt to the *clear* passphrase, hash the *result*, and you still get 256 bits. – EML Sep 13 '21 at 10:38
  • @EML and if you don't store the salt to apply it to the given phrase you want to match with the hash, how would you do that? Having a hash from something with a random salt you don't know anymore is just a random block of bits you dan't do anything useful with. – Patrick Cornelissen Sep 14 '21 at 11:28
  • 1
    @PatrickCornelissen - Ok, that was unclear - I use the Posix/libc `cypt`, and the `crypt` output actually includes the hash, so can be used directly for testing. But the output is more than 256 bits, so, basically, exactly what you said... :) – EML Sep 14 '21 at 14:19
78

Encoding options for SHA256's 256 bits:

  1. Base64: 6 bits per char = CHAR(44) including padding character
  2. Hex: 4 bits per char = CHAR(64)
  3. Binary: 8 bits per byte = BINARY(32)
RickNZ
  • 18,198
  • 3
  • 50
  • 65
32

I prefer to use BINARY(32) since it's the optimized way!

You can place in that 32 hex digits from (00 to FF).

Therefore BINARY(32)!

marctrem
  • 770
  • 8
  • 15
  • 10
    +1 - I like optimized...to anyone else happening on this...to use this with MySQL...you can use `UPDATE...SET hash_column=UNHEX(sha256HexString)`. Then, when retrieving it, you `SELECT HEX(hash_column) AS hash_column`. – Kevin Nelson Sep 17 '14 at 21:20
  • A pertinent MySQL doc: https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html – Buttle Butkus Sep 30 '21 at 06:25
24

Why would you make it VARCHAR? It doesn't vary. It's always 64 characters, which can be determined by running anything into one of the online SHA-256 calculators.

ceejayoz
  • 171,474
  • 40
  • 284
  • 355
7

It will be fixed 64 chars, so use char(64)

Noushad
  • 2,910
  • 1
  • 20
  • 14