Question

I need to generate a strong pseudo random digit (string consisting of only characters 0-9) with length of N.

The generated string needs to be hard to predict in order to be used as a voucher code in a payment system.

Please review my code. This is what I have come up with:

import os
import binascii.hexlify
import random

def get_string_random_digit(n):
    r = os.urandom(n*2)
    ri = int(binascii.hexlify(r), 16)
    arr = list(str(ri))
    while len(arr) > n:
        random.shuffle(arr)
        arr.pop()
    return str(''.join(arr))

os.urandom is supposed to be safe to be used in cryptography so I assumed it would be safe enough to use in a payment system for vouchers.

The system will run on Ubuntu 12.04 LTS if it's relevant (urandom is dependent on OS implementation apparently).

I first generate a string of length N*2 with os.urandom. Then I us built in Python random module to reduce the string to half of its length.

Any suggestions?

Is this safe enough?

Was it helpful?

Solution

os.urandom() returns bytes, so you should just reinterpret them as a long or int; you chose to convert it first to hexadecimal and then further convert it to int; this works fine and will work for arbitrary long numbers. You could have used struct to achieve this in one step, but this will not work for very large numbers, so I think that step is just fine (unless you want to do this millions of times each second).

You should strip that random.shuffle part, though. It does not add any "randomness" to your values. Just use str(ri)[-n:] if you need a string of length n.

OTHER TIPS

Use this:

from random import SystemRandom
def get_random_string(n):
    return int(SystemRandom().random()*10**n)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top