mk wrote: > 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. :-/ > When you've got as much experience as Paul?
regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/ Holden Web LLC http://www.holdenweb.com/ UPCOMING EVENTS: http://holdenweb.eventbrite.com/ -- http://mail.python.org/mailman/listinfo/python-list