310

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
  • 155,785
  • 88
  • 678
  • 743
Tony Stark
  • 24,588
  • 41
  • 96
  • 113
  • 16
    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
  • 4
    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
  • @EML: That link is the correct one for this, and it absolutely does matter that SHA-256 is fast. SHA-x is bad for passphrases, even if you know what you're doing. – President James K. Polk Jan 13 '23 at 13:07
  • @PresidentJamesK.Polk: do the sums. If SHA-x must be run `n` times to break a plain password, then adding a 16-byte salt means that it has to be run `n * 256^16` times instead. Even if the password itself was trivially short - say one printable character - then SHA-x must be run `3 * 10^40` times to test all possibilities. If you've got a GPU setup that runs at 11 billion SHA-256 ops/second, this is `3 * 10^30` seconds. This is *vastly* longer than the age of the universe. Ergo, the fact that SHA-x is "fast" is utterly irrelevant. – EML Jan 13 '23 at 13:44
  • @EML: You are completely misunderstanding the function of the salt. The salt is not a secret. – President James K. Polk Jan 13 '23 at 16:00
  • @PresidentJamesK.Polk: the salt is recorded only in the *hash output*, or equivalently, and *is* a secret, unless the attacker has access to the hashes (in `/etc/shadow`, or wherever). If they have that access, it's game over anyway. If the salt wasn't a secret it would be completely pointless. – EML Jan 13 '23 at 16:15
  • @EML: Stop already, you don't know what you're talking about. Do some research. – President James K. Polk Jan 13 '23 at 16:49
  • @PresidentJamesK.Polk: if you have a point to make, explain why the calculation is incorrect, rather than just explaining how clever you are or how stupid I am. – EML Jan 13 '23 at 19:12

5 Answers5

441

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.

ᴍᴇʜᴏᴠ
  • 4,804
  • 4
  • 44
  • 57
Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
  • 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
  • 142
    ...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
85

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,448
  • 3
  • 51
  • 66
35

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
  • 800
  • 8
  • 15
  • 13
    +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
26

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
  • 176,543
  • 40
  • 303
  • 368
8

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

Noushad
  • 2,960
  • 1
  • 21
  • 14