High quality, simple random password generator

前端 未结 27 2366
渐次进展
渐次进展 2020-12-22 17:06

I\'m interested in creating a very simple, high (cryptographic) quality random password generator. Is there a better way to do this?

import os, random, strin         


        
相关标签:
27条回答
  • 2020-12-22 17:07

    You can't trust python's pseudo random number generator when generating a password. It is not necessarily cryptographically random. You are seeding the pseudo random number generator from os.urandom which is a good start. But then you depend on python's generator after that.

    A better choice would be the random.SystemRandom() class which takes random numbers from the same source as urandom. According to the python documentation that should be good enough for cryptographic use. The SystemRandom class gives you everything that the main random class does but you don't need to worry about the pseudorandomness.

    Example code using random.SystemRandom (for Python 3):

    import random, string
    length = 13
    chars = string.ascii_letters + string.digits + '!@#$%^&*()'
    
    rnd = random.SystemRandom()
    print(''.join(rnd.choice(chars) for i in range(length)))
    

    Note: Your mileage may vary - the Python Documentation says that random.SystemRandom availability varies by operating system.

    0 讨论(0)
  • 2020-12-22 17:08

    It is easy :)

    def codegenerator():
        alphabet = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        pw_length = 8
        mypw = ""
    
        for i in range(pw_length):
            next_index = random.randrange(len(alphabet))
            mypw = mypw + alphabet[next_index]
        return mypw
    

    and the do:

    print codegenerator()
    

    Thanks http://xkcd.com/936/

    0 讨论(0)
  • 2020-12-22 17:08

    Here is another implementation (python 2; would require some minor rewrites to get it working in 3) that is much faster than OJW's, which seems to loop through the dictionary for each word, despite the comment/implication to the contrary. Timing of OJW's script on my machine, with an 80,000 IOP SSD:

    real    0m3.264s
    user    0m1.768s
    sys     0m1.444s
    

    The following script loads the whole dictionary into a list, then picks words based on a random selection of the index value, using OJW's regex for filtering.

    This also generates 10 passphrase sets, allows passing command-line parameters to adjust the number of words, and adds number and symbol padding (also adjustable length).

    Sample times for this script:

    real    0m0.289s
    user    0m0.176s
    sys     0m0.108s
    

    Usage: xkcdpass-mod.py 2 4 (for example; these are the default values).

    It prints spaces in the output for easy reading, although I've almost never encountered an online service that allows using them, so I would just ignore them. This could definitely be cleaned up with argparse or getopt and allowing switches for including spaces or not, including/excluding symbols, capitals, etc., plus some additional refactoring, but I haven't gotten to that yet. So, without further ado:

    #!/usr/bin/env python
    #Copyright AMH, 2013; dedicated to public domain.
    import os, re, sys, random
    from sys import argv
    
    def getargs():
        if len(argv) == 3:
            numwords = argv[1]
            numpads = argv[2]
            return(numwords, numpads)
        elif len(argv) == 2:
            numwords = argv[1]
            numpads = 4
            return (numwords, numpads)
        else:
            numwords = 2
            numpads = 4
            return (numwords, numpads)
    
    def dicopen(dictionary="/usr/share/dict/american-english"):
        f = open(dictionary, "r")
        dic = f.readlines()
        return dic
    
    def genPassword(numwords, numpads):
        r = random.SystemRandom()
        pads = '0123456789!@#$%^&*()'
        padding = []
        words = dicopen()
        wordlist = []
        for i in range (0,int(numpads)):
            padding.append(pads[r.randint(0,len(pads)-1)])
        #initialize counter for only adding filtered words to passphrase
        j = 0
        while (j < int(numwords)):
            inclusion_criteria = re.compile('^[a-z]{5,10}$')
            #Select a random number, then pull the word at that index value, rather than looping through the dictionary for each word
            current_word = words[r.randint(0,len(words)-1)].strip()
            #Only append matching words
            if inclusion_criteria.match(current_word):
                wordlist.append(current_word)
                j += 1
            else:
            #Ignore non-matching words
                pass
        return(" ".join(wordlist)+' '+''.join(padding))
    
    if(__name__ == "__main__"):
        for i in range (1,11):
           print "item "+str(i)+"\n"+genPassword(getargs()[0], getargs()[1])
    

    Sample output:

    [✗]─[user@machine]─[~/bin]
    └──╼ xkcdpass-mod.py
    item 1
    digress basketball )%^)
    item 2
    graves giant &118
    item 3
    impelled maniacs ^@%1
    

    And going for the full "correct horse battery staple" (CHBS), no padding:

    ┌─[user@machine]─[~/bin]
    └──╼ xkcdpass-mod.py 4 0
    item 1
    superseded warred nighthawk rotary 
    item 2
    idealize chirruping gabbing vegan 
    item 3
    wriggling contestant hiccoughs instanced 
    

    According to https://www.grc.com/haystack.htm, for all practical purposes, assuming 100 trillion guesses per second (i.e., 100 TH/s) the shorter version would take about 50-60 million centuries to crack; the full CHBS = 1.24 hundred trillion trillion centuries; adding padding to that, 15.51 trillion trillion trillion centuries.

    Even enlisting the entire Bitcoin mining network (~2500 TH/s as of this writing), the short version would still likely take 250-300 million years to break, which is probably secure enough for most purposes.

    0 讨论(0)
  • 2020-12-22 17:08

    This is more for fun than anything. Scores favorably in passwordmeter.com but impossible to remember.

    #!/usr/bin/ruby
    
    puts (33..126).map{|x| ('a'..'z').include?(x.chr.downcase) ?
                           (0..9).to_a.shuffle[0].to_s + x.chr :
                           x.chr}.uniq.shuffle[0..41].join[0..41]
    
    0 讨论(0)
  • 2020-12-22 17:09

    Yes, no amatuer hacker is going to be cracking that password. Now, after this I recommend continuing on your random password generator project and make a UI or GUI interface either with Tkinter or Flask so others can use it. For example, I found this nice little project just by searching, 'password generator python UI'. https://passwordgenerator.pythonanywhere.com/

    Maybe you'd like to make something similar to above? Its a good skill to know how to implement python into web development.

    Good luck.

    Peace out

    0 讨论(0)
  • 2020-12-22 17:10
    import uuid
    print('Your new password is: {0}').format(uuid.uuid4())
    
    0 讨论(0)
提交回复
热议问题