How can I implement a CSPRNG algorithm in python 2.7?
In python 3.6 there is the secrets module, but I have not found anything for python 2.7
Use the os.urandom() and andom.SystemRandom class to secure random generator in Python 2
Get systemRandom instance out of random class.
Example of systemRandom:-
import random
systemRandom = random.SystemRandom()
SystemRandom.randint()
randomNumber=systemRandom.randint(1,30)
Example of os.urandom
import os
import struct
print(struct.unpack('i', os.urandom(4)))
print(struct.unpack('i', os.urandom(4)))
Refer to this to get started with CSPRNG.
cryptographically secure pseudorandom number generator (CSPRNG)
>>> import random
>>> random.SystemRandom().randint(2**128, 2**(128+1))
414898192462243312770563947893545439929L
>>>
>>> random.SystemRandom().randint(2**128, 2**(128+1))
551865749877602333306492786340710356728L
>>>
>>> random.SystemRandom().randint(2**128, 2**(128+1))
536575901254084412494463427722820032319L
Related
I am trying to generate true random numbers that would be considered cryptographically secure in MicroPython (a variant of Python that is used for microcontrollers). MicroPython does not currently support Python's secrets library.
I understand that I can use os.urandom to generate cryptographically secure random numbers, but would like to bring in the conveniences of setting minimums, maximums, ranges, choices, etc... that are available in Python's (and MicroPython's) random library.
In order to do this, I am contemplating "seeding" the pseudo random number generator with a sufficiently large input from os.urandom (please see example code below). This code considers some of the concepts described here: https://stackoverflow.com/a/72908523/17870197
What are the security implications of this approach? Would numbers output by this code be considered cryptographically secure?
import os
import random
count = 4
def generate_true_random_int(min_int, max_int):
seed_bytes = os.urandom(32)
seed_int = int.from_bytes(seed_bytes, "big")
random.seed(seed_int)
return random.randint(min_int, max_int)
for x in range(count):
min_int = 1
max_int = 9999
true_random_int = generate_true_random_int(min_int, max_int)
print(true_random_int)
I am using Sublime Text3. I am encountering a problem with the choices attribute with the random module. I do not have the same name in any path or directory. The other attributes of random work just fine.
import random
import string
letters = string.ascii_lowercase
print(letters)
gen = random.choices(letters, k=16)
print(gen)
Here is the error code:
abcdefghijklmnopqrstuvwxyz
Traceback (most recent call last):
File "/home/anon/.config/sublime-text-3/Packages/User/test.py", line 6, in <module>
gen = random.choices(letters)
AttributeError: 'module' object has no attribute 'choices'
What are the common causes of this problem?
There's no random.choices in Python 2. You can use random.sample in Python 2.
gen = random.sample(letters, k=16)
random.choices is included in Python 3
It would seem you are using a version of Python that is older than 3.6 which is when random.choices was introduced. You can see it listed at the bottom of this function description here
You can verify your version by running
import sys
sys.version
I encountered the same error when I used Python 2.7.
As a workaround, I simply used random.choice instead of random.choices, in a way as
foo = [random.choice(my_list) for _ in range(50)]
Although we do not have random.choices in Python 2.7, we have random.choice (the former is multiple choices with duplicates, while the latter single choice).
I am realized that default hashlib.sha3_256 hasher does not calculates hashes like other solution, for instance, other python's modules. Below, for instance, I comparing hashlib and sha3 implementation of sha2_256 algorithm on Python 3.6.3.
Implemetation from sha3 gaves correct result (according to other internet resources) while hashlib.sha3_256 result is completely different. How it could be? Am I missed something?
import sha3
import hashlib
def test(s):
k = sha3.keccak_256()
k.update(s.encode())
print('test string="{s}", sha3.keccak_256()="{h}"'.format(s=s, h=k.hexdigest()))
h = hashlib.sha3_256()
h.update(s.encode())
print('test string="{s}", hashlib.keccak_256()="{h}"'.format(s=s, h=h.hexdigest()))
test('')
test('eth')
test('foo.bar')
Results:
test string="", sha3.keccak_256()="c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
test string="", hashlib.keccak_256()="a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
test string="eth", sha3.keccak_256()="4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0"
test string="eth", hashlib.keccak_256()="4b3cdfda85c576e43c848d43fdf8e901d8d02553fec8ee56289d10b8dc47d997"
test string="foo.bar", sha3.keccak_256()="461e2b648c9a6c0c3e2cab45884ae0fcab21c655fcf588f2a45e6596e3e0e9a7"
test string="foo.bar", hashlib.keccak_256()="e55dea66e750540f599874a18596745b0c5705bc6873ca3ef1ccd2acbba88670"
I think they are different implementations:
>>> hashlib.sha3_256("asdf".encode()).hexdigest()
'dd2781f4c51bccdbe23e4d398b8a82261f585c278dbb4b84989fea70e76723a9'
>>> sha3.sha3_256("asdf".encode()).hexdigest()
'dd2781f4c51bccdbe23e4d398b8a82261f585c278dbb4b84989fea70e76723a9'
>>> sha3.keccak_256("asdf".encode()).hexdigest()
'4c8f18581c0167eb90a761b4a304e009b924f03b619a0c0e8ea3adfce20aee64'
After a search, I find that's true.
https://github.com/status-im/nim-keccak-tiny/issues/1
edit
After further search... It seems keccak_256 is not a standard implementation.
With the following code,
# $ pip install pysha3
import sys
if sys.version_info < (3, 4):
import sha3
import hashlib
s = hashlib.new("sha3_512")
s.update(b"")
print(s.hexdigest())
I am getting
0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e
instead of
a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26
cf. https://en.wikipedia.org/wiki/SHA-3#Examples_of_SHA-3_variants
Could anyone advise me?
The pysha3 module you found was based on an draft of the SHA-3 specification, before it was standardised.
The module was created as a POC for Python issue 16113, and the code has not been updated since 2012. The NIST standard wasn't finalised until October 2015. As such, the implementation can't be used if you expect it to follow the released standard.
That ticket links to an implementation that does claim to have been updated to the standard: https://github.com/bjornedstrom/python-sha3. That package doesn't appear to be listed on PyPI, but can be installed with pip directly from GitHub:
pip install git+https://github.com/bjornedstrom/python-sha3
and this package does produce the expected result:
>>> import hashlib
>>> import sha3
>>> hashlib.sha3_512(b'').hexdigest()
b'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'
This package doesn't patch the built-in hashlib.new() constructor, but that's easily done by plugging in the constructor into the module cache:
>>> hashlib.__builtin_constructor_cache['sha3_512'] = sha3.sha3_512
>>> hashlib.new('sha3_512')
<sha3.SHA3512 object at 0x10b381a90>
SHA3 has been added to the built-in hashlib module in Python 3.6:
What’s New In Python 3.6
The SHA-3 hash functions sha3_224(), sha3_256(), sha3_384(),
sha3_512(), and SHAKE hash functions shake_128() and shake_256() were
added. (Contributed by Christian Heimes in issue 16113. Keccak Code
Package by Guido Bertoni, Joan Daemen, Michaël Peeters, Gilles Van
Assche, and Ronny Van Keer.)
It can be used in the follow way:
>>> import sys
>>> import hashlib
>>> s = hashlib.new("sha3_512") # sha3_224, sha3_256 and sha3_384 are also available
>>> s.update(b"")
>>> print(s.hexdigest())
a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26
How do I generate a unique session id in Python?
UPDATE: 2016-12-21
A lot has happened in a the last ~5yrs. /dev/urandom has been updated and is now considered a high-entropy source of randomness on modern Linux kernels and distributions. In the last 6mo we've seen entropy starvation on a Linux 3.19 kernel using Ubuntu, so I don't think this issue is "resolved", but it's sufficiently difficult to end up with low-entropy randomness when asking for any amount of randomness from the OS.
I hate to say this, but none of the other solutions posted here are correct with regards to being a "secure session ID."
# pip install M2Crypto
import base64, M2Crypto
def generate_session_id(num_bytes = 16):
return base64.b64encode(M2Crypto.m2.rand_bytes(num_bytes))
Neither uuid() or os.urandom() are good choices for generating session IDs. Both may generate random results, but random does not mean it is secure due to poor entropy. See "How to Crack a Linear Congruential Generator" by Haldir or NIST's resources on Random Number Generation. If you still want to use a UUID, then use a UUID that was generated with a good initial random number:
import uuid, M2Crypto
uuid.UUID(bytes = M2Crypto.m2.rand_bytes(num_bytes)))
# UUID('5e85edc4-7078-d214-e773-f8caae16fe6c')
or:
# pip install pyOpenSSL
import uuid, OpenSSL
uuid.UUID(bytes = OpenSSL.rand.bytes(16))
# UUID('c9bf635f-b0cc-d278-a2c5-01eaae654461')
M2Crypto is best OpenSSL API in Python atm as pyOpenSSL appears to be maintained only to support legacy applications.
You can use the uuid library like so:
import uuid
my_id = uuid.uuid1() # or uuid.uuid4()
Python 3.6 makes most other answers here a bit out of date. Versions including 3.6 and beyond include the secrets module, which is designed for precisely this purpose.
If you need to generate a cryptographically secure string for any purpose on the web, refer to that module.
https://docs.python.org/3/library/secrets.html
Example:
import secrets
def make_token():
"""
Creates a cryptographically-secure, URL-safe string
"""
return secrets.token_urlsafe(16)
In use:
>>> make_token()
'B31YOaQpb8Hxnxv1DXG6nA'
import os, base64
def generate_session():
return base64.b64encode(os.urandom(16))
It can be as simple as creating a random number. Of course, you'd have to store your session IDs in a database or something and check each one you generate to make sure it's not a duplicate, but odds are it never will be if the numbers are large enough.