How would I create a random, 16-character base-62 salt in python? I need it for a protocol and I'm not sure where to start. Thanks.
8 Answers
You shouldn't use UUIDs, they are unique, not random: Is using a CreateUUID() function as salt a good idea?
Your salts should use a cryptographically secure random numbers, in python 2.4+, os.urandom is the source of these (if you have a good timing source).
# for some given b62encode function
salt = b62encode(os.urandom(16))
you could also use a generator from bcrypt or other awesome crypto/hashing library that is well known and vetted by the people much more expert than I am.
import bcrypt
salt = bcrypt.gensalt()
# will be 29 chars you can then encode it however you want.
-
1It gives me an error: ImportError: No module named bcrypt – dorado Apr 09 '15 at 08:12
-
3pip install bcrypt should remove the error... show that the bcrypt package is not installed in your computer --- anurageldorado – Transformer Jun 06 '15 at 02:03
-
Your base_64 example does not work. A hash may contain `[./a-zA-Z0-9]`, yours will additionally contain `+`, `=` and `\n`. – cdauth Dec 18 '15 at 05:29
-
@cdauth given that I misread the question to begin with (base 62 was asked for), I've since updated this to reflect this. I assume that their exists an encoding function though - easy enough to find one of those on SO. – yarbelk Dec 28 '15 at 07:50
>>> import random
>>> ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
>>> chars=[]
>>> for i in range(16):
chars.append(random.choice(ALPHABET))
>>> "".join(chars)
'wE9mg9pu2KSmp5lh'
This should work.

- 4,714
- 3
- 38
- 50
-
21Nice answer, but the last 4 lines can be done more idiomatically with just `''.join(random.choice(ALPHABET) for i in range(16))` – Scott Griffiths Mar 14 '11 at 09:43
-
1@ScottGriffiths I wouldn't say that it is more idiomatic because it is a one liner... It is a nice one line though, so awesome :) – Mikle Jul 29 '12 at 22:59
-
1
-
-
Also consider creating the alphabet with: `string.ascii_letters + string.digits` – Sam Bull Dec 04 '17 at 15:26
-
4Also see secrets.choice (in 3.6+) for a cryptographically secure version, replacing random.choice in the example. – Sam Bull Dec 04 '17 at 15:49
-
This comment is outdated, are we able to change the accepted answer? – Ash Oldershaw Jul 09 '20 at 10:56
Old question, new solution with secrets
import secrets
random_string = secrets.token_hex(8)
Will produce a cryptographically strong 16-character random string.
Use this over standard pseudo-random number generators as they are much less secure.
To quote from the secrets page:
The secrets module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.
In particularly, secrets should be used in preference to the default pseudo-random number generator in the random module, which is designed for modelling and simulation, not security or cryptography.

- 302
- 2
- 13

- 516
- 5
- 12
These days there is an official mksalt
method in the crypt
module.
It does not give you a simple 16 char long string but adds $digit$
in front required by most hashing functions anyway. If you are hashing passwords this is probably much safer to use.
import crypt
crypt.mksalt(crypt.METHOD_SHA512)
Generates outputs like the following:
$6$wpg9lx1sVFNFSCrP

- 620
- 1
- 10
- 31
-
2
-
Updating an old answer, these days the `crypt` module is deprecated since Python version 3.11, and will be removed in version 3.13 (see [PEP594](https://peps.python.org/pep-0594/#crypt)) – lorenzli Jan 18 '23 at 15:32
in base64:
import random, base64, struct
rand_float = random.SystemRandom().random()
salt = base64.b64encode((struct.pack('!d', rand_float)))
this will be 12 chars

- 2,858
- 23
- 22
import random
import string
def get_salt(size=16, chars=None):
if not chars:
chars = ''.join(
[string.ascii_uppercase,
string.ascii_lowercase,
string.digits]
)
return ''.join(random.choice(chars) for x in range(size))

- 2,793
- 22
- 20
-
What are your thoughts on the salting principal of "salts should be unique, not random"? – T.Woody Apr 08 '19 at 20:24
-
i think you should use 'secrets' module to generate secure randomness https://docs.python.org/3/library/secrets.html it specifically crafted for this kind of jobs

- 1
- 3
-
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/34545468) – Chenmunka Jun 17 '23 at 09:31
I kind of like:
import md5, uuid
m = md5.md5()
m.update(uuid.uuid4())
print m.digest()[:16]
That will be very, very random.

- 23,641
- 4
- 57
- 70
-
1Did you mean `m.update(str(uuid.uuid4()))`? And also `m.hexdigest()[:16]`? But still, that wouldn't be in `base62` right? – Utku Zihnioglu Mar 14 '11 at 02:31
-
Sorry, you're right about the code. I figure since my solution uses a subset of the base62 characters it might work for the original poster. – A. Jesse Jiryu Davis Mar 14 '11 at 04:33