Archive

Posts Tagged ‘urandom’

[flask] generate a secret key

January 1, 2015 1 comment

Problem
To implement CSRF protection, Flask-WTF needs the application to configure an encryption key. This key is used to generate encrypted tokens that are used to verify the authenticity of requests with form data.

It looks like this:

app = Flask(__name__)
app.config['SECRET_KEY'] = '<the super secret key comes here>'

What secret key to use? How to generate this secret key?

Solution #1
In the official Quickstart the following method is suggested:

>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'

Just take that thing and copy/paste it into your code and you’re done.

Solution #2
In Django, when you create a new project, you get a settings file that contains a freshly generated 50 characters long secret key. Why not reuse this part from Django? The relevant section was easy to locate in the source code of Django:

import random
random = random.SystemRandom()

def get_random_string(length=12,
                      allowed_chars='abcdefghijklmnopqrstuvwxyz'
                                    'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
    """
    Returns a securely generated random string.

    The default length of 12 with the a-z, A-Z, 0-9 character set returns
    a 71-bit value. log_2((26+26+10)^12) =~ 71 bits.

    Taken from the django.utils.crypto module.
    """
    return ''.join(random.choice(allowed_chars) for i in range(length))

def get_secret_key():
    """
    Create a random secret key.

    Taken from the Django project.
    """
    chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
    return get_random_string(50, chars)

Its usage is very simple: just call the “get_secret_key()” function and copy/paste the output into your code.

Categories: django, flask Tags: , ,

Generate a 192-bit random number

October 4, 2013 2 comments
import os
os.urandom(24)    # length: 24 bytes, i.e. 24*8=192 bits

See the doc. here.

Formatting its output:

>>> os.urandom(24)
'\x17\x96e\x94]\xa0\xb8\x1e\x8b\xee\xdd\xe9\x91^\x9c\xda\x94\t\xe8S\xa1Oe_'
>>> os.urandom(24).encode('hex')
'cd48e1c22de0961d5d1bfb14f8a66e006cfb1cfbf3f0c0f3'
>>> int(os.urandom(24).encode('hex'), 16)
625318378251135334886162535673249000280269152689162062986L
>>> bin(int(os.urandom(24).encode('hex'), 16))
'0b10100010101001110001101011101111010000111101010010110011111101111101111010100111100000001010100100001000100101010011100001001100011000011000000101101111100001011111011101001110011010001000010'

Update (20170523)
The code above is for Python 2. Here is the Python 3 version:

>>> import os
>>> os.urandom(24)
b':\xea\x8b\xb8\xf4\x04q\xc9$\xd9B\xdf\xaf\xcer\xa0t`Q:\xab{&\xfc'
>>> os.urandom(24).hex()
'11fe838db0c5f661b09f2f7a8de5ac44395e2fdc8128d211'
>>> int(os.urandom(24).hex(), 16)
1970467794856825403422320664826041246218521986958597162907
>>> bin(int(os.urandom(24).hex(), 16))
'0b111101001000010010001110011110010001101100000010011000000001111001101111011111010111110111011110110110110001111010100100000110110111101011000100011010001111001110111001110001010101011001001001'
Categories: python Tags: ,

Generate random hash

Problem
MongoDB generates 96 bit hash values that are used as primary keys. In a project of mine I also needed randomly generated primary keys so I decided to go the MongoDB way. So the question is: how to generate 96 bit hash values with Python?

Solution

#!/usr/bin/env python

import random


def my_hash(bits=96):
    assert bits % 8 == 0
    required_length = bits / 8 * 2
    s = hex(random.getrandbits(bits)).lstrip('0x').rstrip('L')
    if len(s) < required_length:
        return my_hash(bits)
    else:
        return s


def main():
    for _ in range(3):
        print my_hash()

#########################################################

if __name__ == "__main__":
    main()

Sample output:

f4bf4a4c949d7beee38d84a3
457ef2f29f462a4f1e54b61e
dc921ad1e6c32bc8ce8503c8

Another (but about 3.5 times slower) solution:

def my_hash(bits=96):
    assert bits % 8 == 0
    return os.urandom(bits/8).encode('hex')

urandom needs the number of bytes as its parameter.

Tips from here.

Update (20130813)
I found a related work called SimpleFlake. SimpleFlake generates 64 bit IDs, where the ID is prefixed with a millisecond timestamp and the remaining bits are completely random. It has the advantage that IDs show the chronological order of ID creation.