user2122589
user2122589

Reputation: 273

How to create a non-random salt from string for bcrypt.hashpw

First off I read this question and understand one should not use non-random salts, but for this case I will need to:How can I set salt for bcrypt.hashpw?

My code:

import bcrypt

password = "pass"

hashed = bcrypt.hashpw( password, "a0a4310f19")

print hashed

I get error:

ValueError: Invalid salt

How can I convert this string to an accepted salt class? Thank you!

Upvotes: 3

Views: 2098

Answers (1)

paxdiablo
paxdiablo

Reputation: 881083

My understanding is that the salt has to be a 128-bit value (16 octets) encoded with base-64 (24 characters).

If you want to use a fixed salt for (say) debugging, I'd generate one with the gensalt() function, then simply print that out and use it for all eternity, rather than trying some arbitrary value like a0a4310f19.

If, for some reason, you need to use that salt in your question, you probably need to expand it out to 128 bits rather than the 40 bits you currently have (assuming they're actually hex values in that string, four bits per character).

Then base64 encode it, adding the salt header to the front.

So, pumping 0000000000000000000000a0a4310f19 into the base64 encoder here gives you AAAAAAAAAAAAAACgpDEPGQ==. Then you can prefix that with the salt header to get:

$2a$12$AAAAAAAAAAAAAACgpDEPGQ==

and that works fine:

import bcrypt

# Show correct format for verification.
print "Example salt format: %s" % (bcrypt.gensalt())

# Hash with fixed pre-calculated salt.
salt = "$2a$12$AAAAAAAAAAAAAACgpDEPGQ=="
print "Fixed salt hashing: %s" % (bcrypt.hashpw("pass", salt))

You could even use Python itself to turn your 10-character string into a base64-encoded salt, rather than relying on an external site:

import bcrypt
import binascii
import base64

# Pre-calculated salt.

fsalt = "$2a$12$AAAAAAAAAAAAAACgpDEPGQ=="

# Your salt value (hex digits).

salt = "a0a4310f19"

# Work out salt based on your value. Could be improved but
#   leaving it like this in case you want to check out all
#   the intermediate values.

csalt = "0" * 32 + salt           # Prefix to >= 32 digits.
csalt = csalt[-32:]               # Only use last 32 digits.
csalt = binascii.a2b_hex(csalt)   # Convert hex digits to binary.
csalt = base64.b64encode(csalt)   # Encode binary with base64.
csalt = "$2a$12$" + csalt         # Prefix with salt header.

# Hash with both salts for comparison.

print "Fixed salt hashing: %s" % (bcrypt.hashpw("pass",fsalt))
print "Calcd salt hashing: %s" % (bcrypt.hashpw("pass",csalt))

If you want a one-liner for setting up csalt, you can use:

csalt = "$2a$12$" + base64.b64encode(binascii.a2b_hex(("0" * 32 + salt)[-32:]))

Upvotes: 4

Related Questions