On 2010-02-24 03:50, Paul Rubin wrote:
The stuff about converting 4 random bytes to a decimal string and then
peeling off 2 digits at a time is pretty awful, and notice that since
2**32 is 4294967296, in the cases where you get 10 digits, the first
2-digit pair is never higher than 42.

Yikes! I didn't think about that. This is probably where (some part of) probability skewing comes from.

Anyway, the passwords for authorized users will be copied and pasted from email into in the application GUI which will remember it for them, so they will not have to remember and type them in. So I have little in the way of limitations of password length - even though in *some* cases somebody might have to (or be ignorant enough) to retype the password instead of pasting it in.

In that case the "diceware" approach is not necessary, even though I will certainly remember this approach for a case when users will have to remember & type the passwords in.

The main application will access the data using HTTP (probably), so the main point is that an attacker is not able to guess passwords using brute force.

Using A-z with 10-char password seems to provide 3 orders of magnitude more combinations than a-z:

>>> 57 ** 10
362033331456891249L
>>> 25 ** 10
95367431640625L

Even though I'm not sure it is worth it, assuming 1000 brute-force guesses per second (which over the web would amount pretty much to DOS), this would take # days:

>>> 57 ** 10 / (1000 * 3600 * 24)
4190200595L
>>> 25 ** 10 / (1000 * 3600 * 24)
1103789L

Even then I'm not getting completely uniform distribution for some reason:

d 39411
l 39376
f 39288
a 39275
s 39225
r 39172
p 39159
t 39073
k 39071
u 39064
e 39005
o 39005
n 38995
j 38993
h 38975
q 38958
c 38938
b 38906
g 38894
i 38847
m 38819
v 38712
z 35321
y 35228
w 35189
x 35075

Code:

import operator

def gen_rand_word(n):
    with open('/dev/urandom') as f:
        return ''.join([chr(ord('a') + ord(x) % 26) for x in f.read(n)])

def count_chars(chardict, word):
    for c in word:
        try:
            chardict[c] += 1
        except KeyError:
            chardict[c] = 0

if __name__ == "__main__":
    chardict = {}
    for i in range(100000):
        w = gen_rand_word(10)
        count_chars(chardict, w)
    counts = list(chardict.items())
    counts.sort(key = operator.itemgetter(1), reverse = True)
    for char, count in counts:
        print char, count

I'd write your code something like this:

     nletters = 5

     def randomword(n):
         with open('/dev/urandom') as f:
             return ''.join([chr(ord('a')+ord(c)%26) for c in f.read(n)])

     print randomword(nletters)

Aw shucks when will I learn to do the stuff in 3 lines well instead of 20, poorly. :-/

Regards,
mk



--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to