3

I am asking for help in last resort, I have a problem with my code that is driving me crazy. I work with both Python 2.7.6 and Python 3.4.3 on Ubuntu 14.04 with the following very simple part of code that I took from there password generator urandom

import os


def random_password(length=20, symbols='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@$^_+&'):
    password = []
    for i in map(lambda x: int(len(symbols)*x/255.0), os.urandom(length)):
        password.append(symbols[i])
    return ''.join(password)

random_password()

password = random_password()

print(password)

This part of code works with python 3.4.3. but randomly give the following error every 2 or 3 run:

Traceback (most recent call last):
  File "/home/jsmith/Documents/PythonProjects/MainFile", line 12, in <module>
    IotaSeed = Gen_Seed()
  File "/home/jsmith/Documents/PythonProjects/MainFile", line 7, in Gen_Seed
    IotaSeed.append(symbols[i])
IndexError: string index out of range

And with Python 2.7.6, it doesn't work at all and give the following error :

Traceback (most recent call last):
  File "PWDGEN.py", line 10, in <module>
    random_password()
  File "PWDGEN.py", line 6, in random_password
    for i in map(lambda x: int(len(symbols)*x/255.0), os.urandom(length)):
  File "PWDGEN.py", line 6, in <lambda>
    for i in map(lambda x: int(len(symbols)*x/255.0), os.urandom(length)):
TypeError: unsupported operand type(s) for /: 'str' and 'float'

I understand how lambda and map works but I just can't find a solution and I can't switch to python 3.4.3 because I coded my main program with 2.7.

What can I do to make it works under python 2.7 and avoid the "string index out of range" error seen in 3.4.3?

Thanks, PGriffin.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
PGriffin
  • 31
  • 2
  • Maybe just fix `"foo" / 12.34` ..? Ie. ensure there are two numbers.. and find out why the expectation that there *was* another number was violated. – user2864740 Feb 16 '18 at 22:36
  • 2
    It was violated because in Python 3 urandom returns a `bytes` object. When you iterate over `bytes` you get `int`'s. In Python 2 urandom returns a `str` object. When you iterate over that you get each character (also of type `str`). In python 2 you need to call `ord(x)` to convert each character to its corresponding `int` value. – jbch Feb 16 '18 at 22:41
  • The index out of range error comes from code that's not included in your question so we can't help you there. – jbch Feb 16 '18 at 22:43
  • It fails in Python3 when the `i` exceeds 67 (the upper bound of `symbols`). In the few tests I have run, that is always 68. – cdarke Feb 16 '18 at 22:44
  • @jbch: the index out of range error comes from the supplied code and is easy to reproduce. – cdarke Feb 16 '18 at 22:46
  • @cdarke Right, I misread. You need to take `len(symbols)-1`. The maximum index of a list is its length-1 because it starts at 0. – jbch Feb 16 '18 at 22:48
  • 1
    So, putting that together, the lambda in Python 2 should be `lambda x: int((len(symbols)-1)*ord(x)/255.0), os.urandom(length)`. – jbch Feb 16 '18 at 22:49
  • But really you're better off using `random.SystemRandom().randint(0, len(symbols)-1)`, it uses urandom behind the scenes and you won't have to do the messy math yourself. – jbch Feb 16 '18 at 22:54
  • It works ! thanks a lot guys for the help! jbch, your code was right, it works like a charm. thanks – PGriffin Feb 16 '18 at 23:09

1 Answers1

1
int(len(symbols)*x/255.0)

can result in len(symbols) when x == 255. To fix that, you could divide by 256 instead. This won’t give evenly-distributed random characters, though, which is undesirable for password generation. Use SystemRandom instead:

import string
from random import SystemRandom


ALPHANUMERICS = string.ascii_letters + string.digits


def random_password(length=20, symbols=ALPHANUMERICS + '@$^_+&'):
    rng = SystemRandom()
    return ''.join(rng.choice(symbols) for _ in range(length))

Compare how often each character appears in a password before:

histogram not characteristic of a uniform distribution

and after:

histogram characteristic of a uniform distribution

Ry-
  • 218,210
  • 55
  • 464
  • 476