我对创建一个非常简单的,高(加密)质量的随机密码生成器感兴趣。有一个更好的方法吗?
import os, random, string
length = 13
chars = string.ascii_letters + string.digits + '!@#$%^&*()'
random.seed = (os.urandom(1024))
print ''.join(random.choice(chars) for i in range(length))
我对创建一个非常简单的,高(加密)质量的随机密码生成器感兴趣。有一个更好的方法吗?
import os, random, string
length = 13
chars = string.ascii_letters + string.digits + '!@#$%^&*()'
random.seed = (os.urandom(1024))
print ''.join(random.choice(chars) for i in range(length))
random.seed
方法,因此random.seed = 'random_string'
基本上会破坏该方法并且什么都不做?你的意思是random.seed('random_string')
?
os.urandom(1024)
获取1024个字节。对我来说似乎有点过分了。播种16或32字节的种子也许更合适。
Answers:
使用密码的困难之处在于使密码足够坚固,并且仍然能够记住它们。如果密码不是人类要记住的密码,那么它实际上并不是密码。
您使用Python的os.urandom()
:很好。对于任何实际目的(甚至是密码学),的输出os.urandom()
都无法与真正的Alea区分。然后,您将其用作中的种子random
,这不太好:一个是非加密PRNG,其输出可能显示某种结构,该结构不会在统计测量工具中注册,但可能会被聪明的攻击者利用。您应该一直努力os.urandom()
。为简单起见:选择一个长度为64的字母,例如字母(大写和小写),数字和两个额外的标点符号(例如'+'和'/')。然后,对于每个密码字符,从中获取一个字节os.urandom()
,减少模64的值(这是无偏的,因为64除以256)并将结果用作chars
数组中的索引。
使用长度为64的字母,每个字符可获得6位熵(因为2 6 = 64)。因此,使用13个字符,您将获得78位的熵。这并不是在所有情况下最终都强大,但已经非常强大(可以用几个月,数十亿美元(而不仅仅是数百万美元)的预算来击败它)。
os.urandom()
返回type bytes
,那么如何减少该mod 64?
chars[ord(os.urandom(1)) % len(chars)]
chars[]
我们正在讨论的数组的长度为64,而256(一个字节的可能值的数量)是64的倍数。 256则选择将有偏差(某些字符比其他字符更有可能)。
就在两天前,Kragen Javier Sitaker在http://lists.canonical.org/pipermail/kragen-hacks/2011-September/000527.html上发布了一个程序来执行此操作(现在消失了-尝试https://github.com / jesterpm / bin / blob / master / mkpasswd)
生成一个随机的,易记的密码:http : //xkcd.com/936/
示例运行:
kragen at inexorable:〜/ devel / inexorable-misc $ ./mkpass.py 5 12您的密码是“学习了保存受损的居住阶段”。这相当于一个60位密钥。
从2008年开始,假设我对廉价的Celeron E1200进行脱机攻击,那么该密码将花费2.5e + 03 CPU年,这是对MS-Cache哈希的离线攻击,这是最常用的密码哈希算法,甚至比简单的MD5还要差。
如今,最常见的密码哈希算法是FreeBSD的迭代MD5。破解此类哈希将需要5.2e + 06 CPU年。
但是现代GPU的破解速度大约是其250倍,因此相同的迭代MD5将在2e + 04 GPU年内出现。
该GPU在2011年每天要花费约1.45美元,因此破解密码需要花费3e + 09美元。
我已经开始使用以这种方式生成的密码来代替同样强度很强的9可打印ASCII字符随机密码。Munroe认为这些密码更容易记忆的说法是正确的。但是,仍然存在一个问题:因为每个字符的熵位数要少得多(大约是1.7,而不是6.6),所以密码中存在很多冗余,因此,诸如ssh定时通道攻击(Song, Wagner和Tian Herbivore攻击,这是我几年前一个凌晨从Bagdad咖啡馆的Bram Cohen那里了解到的,而键盘音频录音攻击则更有可能捕获足够的信息以使密码易于攻击。
我对草食动物攻击的对策(使用9个字符的密码很好用,但对我的新密码却非常烦人)是输入密码,字符之间的延迟时间为半秒,因此计时通道不会携带太多有关密码的信息。实际使用的字符。此外,较短的9个字符的密码本质上为草食动物提供了更少的信息。
其他可能的对策包括使用Emacs shell模式,该模式在识别到密码提示时在本地提示您输入密码,然后立即发送整个密码,并从其他位置复制和粘贴密码。
如您所料,此密码也需要花费较长时间:大约6秒而不是3秒。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import random, itertools, os, sys
def main(argv):
try:
nwords = int(argv[1])
except IndexError:
return usage(argv[0])
try:
nbits = int(argv[2])
except IndexError:
nbits = 11
filename = os.path.join(os.environ['HOME'], 'devel', 'wordlist')
wordlist = read_file(filename, nbits)
if len(wordlist) != 2**nbits:
sys.stderr.write("%r contains only %d words, not %d.\n" %
(filename, len(wordlist), 2**nbits))
return 2
display_password(generate_password(nwords, wordlist), nwords, nbits)
return 0
def usage(argv0):
p = sys.stderr.write
p("Usage: %s nwords [nbits]\n" % argv0)
p("Generates a password of nwords words, each with nbits bits\n")
p("of entropy, choosing words from the first entries in\n")
p("$HOME/devel/wordlist, which should be in the same format as\n")
p("<http://canonical.org/~kragen/sw/wordlist>, which is a text file\n")
p("with one word per line, preceded by its frequency, most frequent\n")
p("words first.\n")
p("\nRecommended:\n")
p(" %s 5 12\n" % argv0)
p(" %s 6\n" % argv0)
return 1
def read_file(filename, nbits):
return [line.split()[1] for line in
itertools.islice(open(filename), 2**nbits)]
def generate_password(nwords, wordlist):
choice = random.SystemRandom().choice
return ' '.join(choice(wordlist) for ii in range(nwords))
def display_password(password, nwords, nbits):
print 'Your password is "%s".' % password
entropy = nwords * nbits
print "That's equivalent to a %d-bit key." % entropy
print
# My Celeron E1200
# (<http://ark.intel.com/products/34440/Intel-Celeron-Processor-E1200-(512K-Cache-1_60-GHz-800-MHz-FSB)>)
# was released on January 20, 2008. Running it in 32-bit mode,
# john --test (<http://www.openwall.com/john/>) reports that it
# can do 7303000 MD5 operations per second, but I’m pretty sure
# that’s a single-core number (I don’t think John is
# multithreaded) on a dual-core processor.
t = years(entropy, 7303000 * 2)
print "That password would take %.2g CPU-years to crack" % t
print "on my inexpensive Celeron E1200 from 2008,"
print "assuming an offline attack on a MS-Cache hash,"
print "which is the worst password hashing algorithm in common use,"
print "slightly worse than even simple MD5."
print
t = years(entropy, 3539 * 2)
print "The most common password-hashing algorithm these days is FreeBSD’s"
print "iterated MD5; cracking such a hash would take %.2g CPU-years." % t
print
# (As it happens, my own machines use Drepper’s SHA-2-based
# hashing algorithm that was developed to replace the one
# mentioned above; I am assuming that it’s at least as slow as the
# MD5-crypt.)
# <https://en.bitcoin.it/wiki/Mining_hardware_comparison> says a
# Core 2 Duo U7600 can do 1.1 Mhash/s (of Bitcoin) at a 1.2GHz
# clock with one thread. The Celeron in my machine that I
# benchmarked is basically a Core 2 Duo with a smaller cache, so
# I’m going to assume that it could probably do about 1.5Mhash/s.
# All common password-hashing algorithms (the ones mentioned
# above, the others implemented in John, and bcrypt, but not
# scrypt) use very little memory and, I believe, should scale on
# GPUs comparably to the SHA-256 used in Bitcoin.
# The same mining-hardware comparison says a Radeon 5870 card can
# do 393.46 Mhash/s for US$350.
print "But a modern GPU can crack about 250 times as fast,"
print "so that same iterated MD5 would fall in %.1g GPU-years." % (t / 250)
print
# Suppose we depreciate the video card by Moore’s law,
# i.e. halving in value every 18 months. That's a loss of about
# 0.13% in value every day; at US$350, that’s about 44¢ per day,
# or US$160 per GPU-year. If someone wanted your password as
# quickly as possible, they could distribute the cracking job
# across a network of millions of these cards. The cards
# additionally use about 200 watts of power, which at 16¢/kWh
# works out to 77¢ per day. If we assume an additional 20%
# overhead, that’s US$1.45/day or US$529/GPU-year.
cost_per_day = 1.45
cost_per_crack = cost_per_day * 365 * t
print "That GPU costs about US$%.2f per day to run in 2011," % cost_per_day
print "so cracking the password would cost about US$%.1g." % cost_per_crack
def years(entropy, crypts_per_second):
return float(2**entropy) / crypts_per_second / 86400 / 365.2422
if __name__ == '__main__':
sys.exit(main(sys.argv))
实施@Thomas Pornin解决方案
import M2Crypto
import string
def random_password(length=10):
chars = string.ascii_uppercase + string.digits + string.ascii_lowercase
password = ''
for i in range(length):
password += chars[ord(M2Crypto.m2.rand_bytes(1)) % len(chars)]
return password
% len(chars)
这种方法对中的前8个字符有一些偏见chars
。这些字母中的每个字母的出现时间为1.95%,而其他字符为1.56%。
我知道这个问题是在2011年发布的,但是对于那些在2014年及以后出现的问题,我有话要说:抵制重新振作的冲动。
在这些情况下,最好的选择是搜索开源软件,例如,将搜索限制为github结果。到目前为止,我发现的最好的事情是:
XKCD方法的另一种实现:
#!/usr/bin/env python
import random
import re
# apt-get install wbritish
def randomWords(num, dictionary="/usr/share/dict/british-english"):
r = random.SystemRandom() # i.e. preferably not pseudo-random
f = open(dictionary, "r")
count = 0
chosen = []
for i in range(num):
chosen.append("")
prog = re.compile("^[a-z]{5,9}$") # reasonable length, no proper nouns
if(f):
for word in f:
if(prog.match(word)):
for i in range(num): # generate all words in one pass thru file
if(r.randint(0,count) == 0):
chosen[i] = word.strip()
count += 1
return(chosen)
def genPassword(num=4):
return(" ".join(randomWords(num)))
if(__name__ == "__main__"):
print genPassword()
样本输出:
$ ./randompassword.py
affluent afford scarlets twines
$ ./randompassword.py
speedboat ellipse further staffer
生成密码时,您不能相信python的伪随机数生成器。它不一定是密码随机的。您正在从中植入伪随机数生成器os.urandom
这是一个不错的开始。但是之后,您将依赖于python的生成器。
更好的选择是random.SystemRandom()
使用与来源相同的随机数的类urandom
。根据python文档,对于加密使用应该足够好了。的SystemRandom
班给你的一切,主随机类做,但你并不需要对伪随机性担心。
使用random.SystemRandom的示例代码(对于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)))
注意:您的里程可能会有所不同-Python文档说random.SystemRandom可用性因操作系统而异。
/dev/urandom
)被认为是加密安全的。请参阅security.stackexchange.com/questions/3936/…。
/dev/urandom
除非您具有专门的硬件,否则所有(包括)都是伪随机的。
LavaRnd
)。
考虑到您的评论,
我只需要能够生成比我脑子里想出的密码更安全的密码即可。
似乎您想使用程序来生成密码,而不是仅仅作为练习来编写密码。最好使用现有的实现,因为如果您犯了一个错误,则输出可能会受到影响。了解有关随机数生成器攻击的信息;特别是Debian中的一个著名的RNG错误暴露了人们的SSL私钥。
因此,请考虑使用pwgen
。它提供了多个选项,您应该根据计划使用密码的方式来选择这些选项。
/dev/urando
&/dev/random
与真正的随机性没有区别(系统启动后的前10分钟左右除外)
这很容易 :)
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
和做:
print codegenerator()
import random
r = random.SystemRandom()
def generate_password(words, top=2000, k=4, numbers=None, characters=None,
first_upper=True):
"""Return a random password based on a sorted word list."""
elements = r.sample(words[:top], k)
if numbers:
elements.insert(r.randint(1, len(elements)), r.choice(numbers))
if characters:
elements.insert(r.randint(1, len(elements)), r.choice(characters))
if first_upper:
elements[0] = elements[0].title()
return ''.join(elements)
if __name__ == '__main__':
with open('./google-10000-english-usa.txt') as f:
words = [w.strip() for w in f]
print(generate_password(words, numbers='0123456789', characters='!@#$%'))
os.urandom()
当然可以改进,但这是我使用的。
令人鼓舞的@Thomas Pornin解决方案(无法评论@Yossi不精确的答案):
import string, os
chars = string.ascii_letters + string.digits + '+/'
assert 256 % len(chars) == 0 # non-biased later modulo
PWD_LEN = 16
print(''.join(chars[c % len(chars)] for c in os.urandom(PWD_LEN)))
感谢Stephan Lukits的python3更新
您的实现存在一些问题:
random.seed = (os.urandom(1024))
这不会为随机数生成器提供种子。它将seed
函数替换为字节串。您需要致电seed
,例如random.seed(…)
。
print ''.join(random.choice(chars) for i in range(length))
Python的默认PRNG是Mersenne Twister,它不是具有加密功能的PRNG,因此我对将其用于加密目的非常谨慎。该random
模块包括random.SystemRandom
,至少在大多数* nix系统上,应使用CSPRNG。但是,
random.choice(chars)
……实现为……
def choice(self, seq):
"""Choose a random element from a non-empty sequence."""
return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty
…在Python 2中。不幸的是,self.random
这是一个C函数,因此很难看到它。这里的代码味道是,该代码几乎肯定不会统一选择。该代码在Python 3中已完全更改,并且在确保一致性方面做得更好。需要randrange
注意的Python 3文档,
在版本3.2中进行了更改:
randrange()
在产生均等分布的值方面更为复杂。以前它使用的样式int(random()*n)
可能会产生稍微不均匀的分布。
randrange
并且choice
都调用相同的方法(_randbelow
引擎盖下)。
在Python 3中,choice
可以;在Python 2中,它仅接近统一分布,但不能保证均匀分布。由于这是加密货币,因此我依靠栅栏的“绝大部分”,并希望获得这一保证。
针对当前主题构建了自己的CLI答案(完整的源代码位于以下URL):
http://0netenv.blogspot.com/2016/08/password-generator-with-argparse.html
使用argparse编写了密码生成器。希望这对某人有帮助(构建密码生成器或使用argparse)!
无论哪种方式,构建都很有趣!
$ ./pwgen.py -h
usage: pwgen.py [-h] [-c COUNT] [-a] [-l] [-n] [-s] [-u] [-p]
Create a random password
Special characters, numbers, UPPERCASE -"Oscar",
and lowercase -"lima" to avoid confusion.
Default options (no arguments): -c 16 -a
Enjoy! --0NetEnv@gmail.com
optional arguments:
-h, --help show this help message and exit
-c COUNT, --count COUNT
password length
-a, --all same as -l -n -s -u
-l, --lower include lowercase characters
-n, --number include 0-9
-s, --special include special characters
-u, --upper include uppercase characters
-p, --license print license and exit
这是代码:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
license = """
# pwgen -- the pseudo-random password generator
#
# This software is distributed under the MIT license.
#
# The MIT License (MIT)
#
# Copyright (c) 2016 0NetEnv 0netenv@gmail.com
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the
# Software without restriction, including without
# limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice
# shall be included in all copies or substantial portions
# of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
# IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# NOTE:
# This software was tested on Slackware 14.2, Raspbian, &
# Mac OS X 10.11
#
"""
import string
import random
import sys
# first time using argparse library
import argparse
# wanted to change the formatting of the help menu a little bit, so used RawTextHelpFormatter directly
from argparse import RawTextHelpFormatter
typo = ''
c = 16
counter = 0
line = '-' * 40
# CREATE FUNCTION for PWGEN
def pwgen(z, t):
# EMPTY SET OF CHARACTERS
charsset = ''
# UPPERCASE -"O"
U = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'
# lowercase -"l"
L = 'abcdefghijkmnopqrstuvwxyz'
N = '0123456789'
S = '!@#$%^&*?<>'
# make sure we're using an integer, not a char/string
z = int(z)
for type in t:
if 'u' in t:
charsset = charsset + U
if 'l' in t:
charsset = charsset + L
if 'n' in t:
charsset = charsset + N
if 's' in t:
charsset = charsset + S
if 'a' == t:
charsset = charsset + U + L + N + S
return ''.join(random.choice(charsset) for _ in range(0, int(z)))
# GET ARGUMENTS using ARGPARSE
parser = argparse.ArgumentParser(description='\n Create a random password\n\
Special characters, numbers, UPPERCASE -"Oscar",\n\
and lowercase -"lima" to avoid confusion.\n\
Default options (no arguments): -c 16 -a\n\
\t\tEnjoy! --0NetEnv@gmail.com', formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-c", "--count", dest="count", action="store", help="password length")
parser.add_argument("-a", "--all", help="same as -l -n -s -u", action="store_true")
parser.add_argument("-l", "--lower", help="include lowercase characters", action="store_true")
parser.add_argument("-n", "--number", help="include 0-9", action="store_true")
parser.add_argument("-s", "--special", help="include special characters", action="store_true")
parser.add_argument("-u", "--upper", help="include uppercase characters", action="store_true")
parser.add_argument("-p", "--license", help="print license and exit", action="store_true")
# COLLECT ARGPARSE RESULTS
results = args = parser.parse_args()
# CHECK RESULTS
# Check that a length was given.
# If not, gripe and exit.
if args.count == '0':
print ("Input error:\nCannot create a zero length password.\nExiting")
exit (0)
# check character results and add to counter if
# selection is made.
if args.lower:
typo = typo + 'l'
counter = counter + 1
#print "lower"
if args.number:
typo = typo + 'n'
counter = counter + 1
#print "number"
if args.special:
typo = typo + 's'
counter = counter + 1
#print "special"
if args.upper:
typo = typo + 'u'
counter = counter + 1
#print "upper"
if args.all:
typo = 'a'
counter = counter + 1
#print "all"
if args.license:
print (license)
exit (1)
# CHECK COUNTER
# Check our counter and see if we used any command line
# options. We don't want to error out.
# try it gracefully. If no arguments are given,
# use defaults and tell the user.
# args.count comes from argparse and by default requires
# an input to '-c'. We want to get around that for the
# sake of convenience.
# Without further adieu, here's our if statement:
if args.count:
if counter == 0:
typo = 'a'
print ("defaulting to '--all'")
print (line)
print (pwgen(results.count,typo))
else:
if counter == 0:
typo = 'a'
print ("defaulting to '--count 16 --all'")
print (line)
print (pwgen(c,typo))
print (line)
#print typo
Base64让我们以人类可读/可写的方式对二进制数据进行编码,而不会丢失数据。
import os
random_bytes=os.urandom(12)
secret=random_bytes.encode("base64")
我喜欢语言学,在我的方法中,我通过交替辅音和元音来创建具有高熵水平的令人难忘的伪单词。
Python代码:
import random
import string
def make_pseudo_word(syllables=5, add_number=False):
"""Create decent memorable passwords.
Alternate random consonants & vowels
"""
rnd = random.SystemRandom()
s = string.ascii_lowercase
vowels = 'aeiou'
consonants = ''.join([x for x in s if x not in vowels])
pwd = ''.join([rnd.choice(consonants) + rnd.choice(vowels)
for x in range(syllables)]).title()
if add_number:
pwd += str(rnd.choice(range(10)))
return pwd
>>> make_pseudo_word(syllables=5)
'Bidedatuci'
>>> make_pseudo_word(syllables=5)
'Fobumehura'
>>> make_pseudo_word(syllables=5)
'Seganiwasi'
>>> make_pseudo_word(syllables=4)
'Dokibiqa'
>>> make_pseudo_word(syllables=4)
'Lapoxuho'
>>> make_pseudo_word(syllables=4)
'Qodepira'
>>> make_pseudo_word(syllables=3)
'Minavo'
>>> make_pseudo_word(syllables=3)
'Fiqone'
>>> make_pseudo_word(syllables=3)
'Wiwohi'
缺点:
这是另一种实现(python 2;需要一些小的重写才能使其在3中工作),它比OJW的快得多,尽管注释/含义相反,但它似乎在每个单词的字典中循环。在我的计算机上使用80,000 IOP SSD的OJW脚本的时间:
real 0m3.264s
user 0m1.768s
sys 0m1.444s
以下脚本将整个字典加载到列表中,然后使用OJW的正则表达式进行过滤,根据索引值的随机选择来选择单词。
这还会生成10个密码短语集,允许传递命令行参数来调整单词数,并添加数字和符号填充(也可以调整长度)。
此脚本的采样时间:
real 0m0.289s
user 0m0.176s
sys 0m0.108s
用法:xkcdpass-mod.py 2 4(例如,这些是默认值)。
它在输出中打印空格以便于阅读,尽管我几乎从未遇到过允许使用它们的在线服务,因此我将忽略它们。可以肯定地用argparse或getopt清除它,并允许开关是否包含空格,包括/不包括符号,大写字母等,以及一些其他的重构,但是我还没有做到这一点。因此,事不宜迟:
#!/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])
样本输出:
[✗]─[user@machine]─[~/bin]
└──╼ xkcdpass-mod.py
item 1
digress basketball )%^)
item 2
graves giant &118
item 3
impelled maniacs ^@%1
并准备完整的“正确的马电池钉”(CHBS),无需填充:
┌─[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
根据https://www.grc.com/haystack.htm,出于所有实际目的,假设每秒100万亿次猜测(即100 TH / s),较短的版本大约需要50-60百万个世纪才能破解。完整的CHBS = 1.24万亿亿个世纪; 此外,还有15.51万亿亿亿个世纪的填充。
即使征服了整个比特币采矿网络(在撰写本文时,速度约为2500 TH / s),短版本也可能需要花费250-3亿年的时间才能破解,这对于大多数用途而言可能是足够安全的。
import uuid
print('Your new password is: {0}').format(uuid.uuid4())
有点偏离主题,但是我也使用TKinter做到了这一点。希望它可以帮助:
import os, random, string
from tkinter import *
def createPwd():
try:
length = int(e1.get())
except ValueError:
return
chars = string.ascii_letters + string.digits + '!@#$%^&*()?\/'
random.seed = (os.urandom(1024))
e2.config(state=NORMAL)
e2.delete(0,'end')
e2.insert(0,''.join(random.choice(chars) for i in range(length)))
e2.config(state="readonly")
mainWindow = Tk()
mainWindow.title('Password generator')
mainWindow.resizable(0,0)
f0 = Frame(mainWindow)
f0.pack(side=TOP,pady=5,padx=5,fill=X,expand=1)
Label(f0,text="Length: ",anchor=E).grid(row=0,column=0,sticky=E)
e1 = Entry(f0)
e1.insert(0,'12')
e1.grid(row=0,column=1)
btn = Button(f0,text="Generate")
btn['command'] = lambda: createPwd()
btn.grid(row=0,column=2,rowspan=1,padx=10,ipadx=10)
Label(f0,text="Generated password: ",anchor=E).grid(row=1,column=0,sticky=E)
e2 = Entry(f0)
e2.grid(row=1,column=1)
createPwd()
#starting main window
mainWindow.mainloop()
这是一个简单的小型程序,面向无法为自己的公共帐户提供安全密码的人。
只需在命令控制台上运行该程序,然后传入一堆您似乎熟悉的字母,它就会根据您插入的内容生成一系列符号。
当然,该程序不支持多序列生成。
您可以从我的github pull下载代码:https : //github.com/abdechahidely/python_password_generator
from string import ascii_lowercase, ascii_uppercase, digits, punctuation
from random import randint, choice, shuffle
from math import ceil
from re import finditer
lower_cases = ascii_lowercase
upper_cases = ascii_uppercase
lower_upper = dict(zip(lower_cases, upper_cases))
upper_lower = dict(zip(upper_cases, lower_cases))
punctuations = '#$%&@!?.'
space = ' '
class PunctOrDigit():
def __init__(self, number_of_punctuations, number_of_digits):
self.puncts = number_of_punctuations
self.digits = number_of_digits
self.dupl_puncts = self.puncts
self.dupl_digits = self.digits
def PorD(self):
symbol_type = choice('pd')
if symbol_type == 'p':
if self.puncts == 0:
return 'd'
else:
self.puncts -= 1
return symbol_type
if symbol_type == 'd':
if self.digits == 0:
return 'p'
else:
self.digits -= 1
return symbol_type
def reset(self):
self.puncts = self.dupl_puncts
self.digits = self.dupl_digits
def is_empty(text):
for symbol in text:
if symbol != space:
return False
return True
def contain_unauthorized_symbols(text):
for symbol in text:
if symbol in punctuation or symbol in digits:
return True
return False
def user_input():
user_input = input('-- Sentence to transform: ')
while is_empty(user_input) or len(user_input) < 8 or contain_unauthorized_symbols(user_input):
user_input = input('-- Sentence to transform: ')
return user_input
def number_of_punctuations(text):
return ceil(len(text) / 2) - 3
def number_of_digits(text):
return ceil(len(text) / 2) - 2
def total_symbols(text):
return (number_of_digits(text) + number_of_punctuations(text),
number_of_punctuations(text),
number_of_digits(text))
def positions_to_change(text):
pos_objct = PunctOrDigit(number_of_punctuations(text), number_of_digits(text))
positions = {}
while len(positions) < total_symbols(text)[0]:
i = randint(0,len(text)-1)
while i in positions:
i = randint(0,len(text)-1)
positions[i] = pos_objct.PorD()
pos_objct.reset()
return positions
def random_switch(letter):
if letter in lower_cases:
switch_or_pass = choice('sp')
if switch_or_pass == 's': return lower_upper[letter]
else: return letter
if letter in upper_cases:
switch_or_pass = choice('sp')
if switch_or_pass == 's': return upper_lower[letter]
else: return letter
def repeated(text):
reps = {}
for letter in set(list(text)):
indexs = [w.start() for w in finditer(letter, text)]
if letter != ' ':
if len(indexs) != 1:
reps[letter] = indexs
return reps
def not_repeated(text):
reps = {}
for letter in set(list(text)):
indexs = [w.start() for w in finditer(letter, text)]
if letter != ' ':
if len(indexs) == 1:
reps[letter] = indexs
return reps
def generator(text, positions_to_change):
rep = repeated(text)
not_rep = not_repeated(text)
text = list(text)
for x in text:
x_pos = text.index(x)
if x not in positions_to_change:
text[x_pos] = random_switch(x)
for x in rep:
for pos in rep[x]:
if pos in positions_to_change:
if positions_to_change[pos] == 'p':
shuffle(list(punctuations))
text[pos] = choice(punctuations)
if positions_to_change[pos] == 'd':
shuffle(list(digits))
text[pos] = choice(digits)
for x in not_rep:
for pos in not_rep[x]:
if pos in positions_to_change:
if positions_to_change[pos] == 'p':
shuffle(list(punctuations))
text[pos] = choice(punctuations)
if positions_to_change[pos] == 'd':
shuffle(list(digits))
text[pos] = choice(digits)
text = ''.join(text)
return text
if __name__ == '__main__':
x = user_input()
print(generator(x, positions_to_change(x)))
这是研究此主题后的随机密码生成器:
`import os, random, string
#Generate Random Password
UPP = random.SystemRandom().choice(string.ascii_uppercase)
LOW1 = random.SystemRandom().choice(string.ascii_lowercase)
LOW2 = random.SystemRandom().choice(string.ascii_lowercase)
LOW3 = random.SystemRandom().choice(string.ascii_lowercase)
DIG1 = random.SystemRandom().choice(string.digits)
DIG2 = random.SystemRandom().choice(string.digits)
DIG3 = random.SystemRandom().choice(string.digits)
SPEC = random.SystemRandom().choice('!@#$%^&*()')
PWD = None
PWD = UPP + LOW1 + LOW2 + LOW3 + DIG1 + DIG2 + DIG3 + SPEC
PWD = ''.join(random.sample(PWD,len(PWD)))
print(PWD)`
这将生成一个随机密码,其中包含1个随机大写字母,3个随机小写字母,3个随机数字和1个随机特殊字符-可以根据需要进行调整。然后,它组合每个随机字符并创建一个随机顺序。我不知道这是否被认为是“高质量”,但是可以完成工作。
我的解决方案基于@Thomas Pornin的答案(已更新)
import os, string
def get_pass(password_len=12):
new_password=None
symbols='+!'
chars=string.ascii_lowercase+\
string.ascii_uppercase+\
string.digits+\
symbols
while new_password is None or \
new_password[0] in string.digits or \
new_password[0] in symbols:
new_password=''.join([chars[ord(os.urandom(1)) % len(chars)] \
for i in range(password_len)])
return new_password
print(get_pass())
此函数返回一个随机密码(密码开头没有数字或符号)。
chars
列表长度为69个字符,而不是64个字符。前缀“ A”的字符显示的频率仅为其余字符的75%。请参阅@foudfou的答案。此外,它一点也不起作用:最后一行应该是print(get_pass())
我最近才开始学习python,这是我今天写的。希望这可以帮助。
import random
characters = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^()}{/<>'
print('Password Length: ')
passwordLength = int(input())
password = ''
for i in range(passwordLength):
password += random.choice(characters)
print(password)
"""
This code below in any shape or form is owned by A.S Gallery
This code is the asnwer for Password Generator quiz - CodeHs
This code works 100%
Have fun exploring !!!
"""
# Imports
import random
import time
print "Hi !!!"
password_output = "this is your new password : "
ask_name = input("Enter your Name : ")
greetings_name = "Hi "+ str(ask_name) + "!!! "
print greetings_name
print "Now we will make your new password using the ULTIMATE password generator !!!"
time.sleep(8)
print "Our password generator will give you multiple choices, you can choose any password generator you want !!! "
time.sleep(8)
print "You can choose if you want a strong password or a weak password !! (strong recommended) "
time.sleep(8)
print "You can also make your own password, to make your own password type own !!! "
time.sleep(8)
print "If you want to choose strong type strong, if weak then type weak !!! "
time.sleep(8)
# Example:
# Returns random number within and including 0 and 10.
def strong_password():
user_input = int(input("Enter a number : "))
print type(user_input)
time.sleep(3)
# calculate_input = user_input * user_input
calculate_types = input("Do you want to add, multiply or mod the numbers : ")
time.sleep(3)
if calculate_types == "add":
calculate_input = user_input + user_input
elif calculate_types == "multiply" :
calculate_input = user_input * user_input
elif calculate_types == "mod":
calculate_input = user_input & user_input
else:
print "Check your spelling and try again :( "
# Random element in a string
time.sleep(4)
want_symbols = input("Do you want symbols ?(Y/N) : ")
time.sleep(4)
random_element = random.choice('abcdefg345')
if want_symbols == "Y":
random_element2 = random.choice('@#()@*($*(@)(*^()*()(#$)*@#)*((@*()@*#)(*)@*($*(%#*)#(*@@_!_()(')
elif want_symbols == "N":
random_element2 = random.choice('29371294203712492703740182903820498201381204AKSJFKSHEHJKFJAODL')
random_element3 = random.choice('abcdefghiiasudasdjsiasdhwudagsjdgaskdjsafgjasj')
random_element4 = random.choice('abcdefghijsdhjaskdhkasjdhakdjhaskdasjdhakjsd')
random_element5 = random.choice('abcdefghijsdhsakjdhsajdldasjdasdjasldas')
random_elements6 = random.choice('129389230928308290382109830293943827492347')
random_elements7 = random.choice('2473285473q9mdnuwyr8KSDJKDSJKL932uc3487389473289479h3289wjdi94802w')
random_elements8 = random.choice('AKDJKAJDKJIKJDUIFHSJHUFRUDIJFDKLDJKDJLJFKLJKLDJLDJKLDJLDJLSKJDKLJDLJDKSLJD')
time.sleep(8)
print str(ask_name) + " " + str(password_output) + str(calculate_input) + str(random_element) + str(random_element2) + str(random_element3) + str(random_element4) + str(random_element5) + str(random_elements6) + str(random_elements7) + str(random_elements8)
def weak_password():
user_input = int(input("Enter a number : "))
print type(user_input)
time.sleep(3)
# calculate_input = user_input * user_input
calculate_types = input("Do you want to add, multiply or mod the numbers : ")
time.sleep(3)
if calculate_types == "add":
calculate_input = user_input + user_input
elif calculate_types == "multiply" :
calculate_input = user_input * user_input
elif calculate_types == "mod":
calculate_input = user_input & user_input
else:
time.sleep(3)
print "Check your spelling and try again :( "
# Random element in a string
random_ness = random.choice("ABCDEFGHI*(#*#$()#*$)(E)(UWIJEDSH(*#U$()UDSLKH)UW*)$(*&#*(YE(*DY#*YUHSLDF:LKDDSDK")
my_tuple = (calculate_input, random_ness, user_input, ask_name)
new_tuple = my_tuple[1]
new_tuple1 = my_tuple[2]
new_tuple2 = my_tuple[3]
time.sleep(7)
print str(ask_name) + str(password_output) + str(new_tuple) + str(new_tuple1) + str(new_tuple2)
def own_password():
my_list = []
ask_times = int(input("How many characters do you want ? (between 1 - 8) : "))
time.sleep(10)
if ask_times > 8:
print "Invalid Request"
elif ask_times < 1:
print "Invalid Request"
else:
time.sleep(2)
print "You CANNOT include symbols or numbers in this option !!! "
for i in range(ask_times):
user_ask = input("Enter the character: ")
time.sleep(0.6)
my_list.append(user_ask)
own_password = "".join(map(str,my_list))
time.sleep(4)
print "Your own password is : " + own_password
strong_pass = input("Do you want a strong password or a weak one or make your own password !! ? : ")
if strong_pass == "strong":
strong_password()
elif strong_pass == "weak":
weak_password()
elif strong_pass == "own":
own_password()
else :
print "Invalid Request"
time.sleep(3)
print "Congrats, on creating your best password !!! I belived you used strong password generator because its the BEST !!"
time.sleep(7)
print "If not, no problem just restart the program and type strong when prompted !!! "
time.sleep(6)
print "Have a nice day !"
这段代码也是CodeH测验的答案(如果有的话)!
是的,没有哪个黑客会破解该密码。现在,在此之后,我建议继续您的随机密码生成器项目,并使用Tkinter或Flask创建UI或GUI界面,以便其他人可以使用它。例如,我只是通过搜索“密码生成器python UI”找到了这个不错的小项目。https://passwordgenerator.pythonanywhere.com/
也许您想做类似上面的事情?了解如何将python实施到Web开发中是一项很好的技能。
祝好运。
和平了