Is this code capable of generating Cryptographically Secure Pseudo-Random Number Generator
Question:
I have a piece of code which generates a string of length 50 to 100 with random characters
the code is :
CharLIST = list('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890')
def NEW(id_len):
_id = ''
while len(_id) < id_len:
_id += random.choice(CharLIST)
return _id
NEW(random.randint(50, 100))
I expect it to generate a completely random string which is not unpredictable
I used a code analyser which said it is not Cryptographically Secure
but it generate random strings which I think are unpredictable based on seeing 200 results
Answers:
No, none of the utilities in random
should be considered secure. Their output is completely deterministic.
This is emphasized in warnings at the top of the module’s documentation:
Python uses the Mersenne Twister as the core generator …. [which], being completely deterministic, is not suitable for all purposes, and is completely unsuitable for cryptographic purposes.
[…]
Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets
module.
As suggested, for cryptographically secure random number generation, you should use the secrets
module:
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 particular, 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.
For your particular use case, the secrets
module provides a secrets.choice
function that works analogously to random.choice
.
Like @Brian said, random isn’t secure with encrypting. Use the secrets module with the built in choice
function instead of random. You can also use the string module to shorten your combinations:
import string
import secrets
CharLIST = string.digits + string.ascii_letters
def NEW():
myPass = "".join(secrets.choice(CharLIST) for i in range(50,100))
return myPass
print(NEW())
I have a piece of code which generates a string of length 50 to 100 with random characters
the code is :
CharLIST = list('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890')
def NEW(id_len):
_id = ''
while len(_id) < id_len:
_id += random.choice(CharLIST)
return _id
NEW(random.randint(50, 100))
I expect it to generate a completely random string which is not unpredictable
I used a code analyser which said it is not Cryptographically Secure
but it generate random strings which I think are unpredictable based on seeing 200 results
No, none of the utilities in random
should be considered secure. Their output is completely deterministic.
This is emphasized in warnings at the top of the module’s documentation:
Python uses the Mersenne Twister as the core generator …. [which], being completely deterministic, is not suitable for all purposes, and is completely unsuitable for cryptographic purposes.
[…]
Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the
secrets
module.
As suggested, for cryptographically secure random number generation, you should use the secrets
module:
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 particular,
secrets
should be used in preference to the default pseudo-random number generator in therandom
module, which is designed for modelling and simulation, not security or cryptography.
For your particular use case, the secrets
module provides a secrets.choice
function that works analogously to random.choice
.
Like @Brian said, random isn’t secure with encrypting. Use the secrets module with the built in choice
function instead of random. You can also use the string module to shorten your combinations:
import string
import secrets
CharLIST = string.digits + string.ascii_letters
def NEW():
myPass = "".join(secrets.choice(CharLIST) for i in range(50,100))
return myPass
print(NEW())