고품질의 간단한 임의 암호 생성기
저는 매우 간단하고 높은 (암호화) 품질의 임의 암호 생성기를 만드는 데 관심이 있습니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?
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))
암호의 어려운 점은 암호를 충분히 강력하게 만들고 기억할 수 있다는 것입니다. 암호가 사람이 기억하기위한 것이 아니라면 실제로는 암호가 아닙니다.
당신은 파이썬을 사용합니다 os.urandom()
: 좋습니다. 실제 목적 (암호화 포함)을 위해의 출력은 os.urandom()
실제 alea와 구별 할 수 없습니다. 그런 다음에서 시드로 사용하는데 random
, 이는 비 암호화 PRNG이고 그 출력은 통계 측정 도구에 등록되지 않지만 지능적인 공격자에 의해 악용 될 수있는 일부 구조를 나타낼 수 있습니다. 당신은 함께 일해야합니다 os.urandom()
. 간단하게하기 위해 : 문자 (대문자 및 소문자), 숫자, 두 개의 추가 구두점 문자 (예 : '+'및 '/')와 같이 길이가 64 인 알파벳을 선택하십시오. 그런 다음 각 암호 문자에 대해에서 1 바이트를 가져와 os.urandom()
모듈로 64 값을 줄이고 (64가 256을 나누기 때문에 편향되지 않음) 결과를 chars
배열의 인덱스로 사용합니다 .
길이가 64 인 알파벳을 사용하면 문자 당 6 비트의 엔트로피를 얻습니다 (2 6 = 64 이기 때문에 ). 따라서 13 개의 문자로 78 비트의 엔트로피를 얻습니다. 이것은 궁극적으로 모든 경우에 강력하지는 않지만 이미 매우 강력합니다 (단순한 수백만이 아닌 수개월 및 수십억 달러로 계산되는 예산으로 패배 할 수 있음).
XKCD는 왜 좋은 설명이 어떻게 생각하는지 강력한 암호가 되지 않습니다를 .
정보 이론과 보안을 이해하고 그렇지 않은 사람과 격분한 논쟁을 벌이는 분들께 진심으로 사과드립니다. -랜달 먼로
그리고이 그림이 설명하는 것의이면에 있는 수학을 이해하지 못한다면 , 암호 학적으로 안전해야하는 것은 작성하지 마십시오. 그렇지 않을 것입니다. 마우스를 내려 놓고 키보드에서 떨어지십시오.
불과 이틀 전에, 크레 이건 하비에르 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 비트 키와 동일합니다.
이 암호는 일반적으로 사용되는 최악의 암호 해싱 알고리즘 인 MS-Cache 해시에 대한 오프라인 공격을 가정 할 때 2008 년부터 저렴한 Celeron E1200을 크랙하는 데 2.5e + 03 CPU- 년이 걸리며 단순한 MD5보다 약간 더 나쁩니다.
요즘 가장 일반적인 암호 해싱 알고리즘은 FreeBSD의 반복 된 MD5입니다. 이러한 해시를 크래킹하는 데는 5.2e + 06 CPU- 년이 걸립니다.
그러나 최신 GPU는 약 250 배 빠르게 크랙 할 수 있으므로 동일한 반복 MD5가 2e + 04 GPU- 년에 떨어질 것입니다.
이 GPU는 2011 년에 실행하는 데 하루에 약 1.45 달러가 들기 때문에 암호를 해독하는 데 드는 비용은 약 3e + 09 달러입니다.
나는 똑같이 강력한 9 개의 인쇄 가능한 ASCII 문자 임의 암호 대신 이렇게 생성 된 암호를 사용하기 시작했습니다. 이러한 암호가 암기하기 훨씬 쉽다는 Munroe의 주장은 옳습니다. 그러나 여전히 문제가 있습니다. 문자 당 엔트로피 비트가 훨씬 적기 때문에 (6.6 대신 약 1.7) 암호에 많은 중복성이 있으므로 ssh 타이밍 채널 공격 (The Song, Wagner와 Tian Herbivore 공격은 몇 년 전 어느 날 아침 Bagdad Café의 Bram Cohen에게서 배웠습니다) 및 키보드 오디오 녹음 공격은 암호를 공격 할 수있는 충분한 정보를 캡처 할 가능성이 훨씬 더 높습니다.
9 자 암호로는 잘 작동하지만 새 암호로 매우 성가신 Herbivore 공격에 대한 나의 대응책은 문자 사이에 0.5 초의 지연 시간을두고 암호를 입력하여 타이밍 채널에 대한 많은 정보를 전달하지 않도록하는 것입니다. 사용 된 실제 문자. 또한, 9 자 암호의 길이가 짧기 때문에 본질적으로 Herbivore 접근 방식은 씹을 정보가 훨씬 적습니다.
다른 가능한 대책으로는 Emacs 셸 모드를 사용하여 암호 프롬프트를 인식 할 때 로컬에서 암호를 입력하라는 메시지를 표시 한 다음 전체 암호를 한 번에 전송하고 다른 곳에서 암호를 복사하여 붙여 넣는 것이 있습니다.
예상대로이 암호는 입력하는 데 시간이 조금 더 걸립니다 (약 3 초가 아닌 약 6 초).
#!/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
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
나는이 질문이 2011 년에 다시 게시 된 것을 알고 있지만, 지금 2014 년과 그 이후에 오는 사람들을 위해 한 가지 말할 것이 있습니다. 바퀴를 되살리려는 욕심에 저항하십시오.
이러한 상황에서 가장 좋은 방법은 오픈 소스 소프트웨어를 검색하는 것입니다. 예를 들어 검색을 github 결과로 제한하십시오. 내가 찾은 가장 좋은 것은 :
https://github.com/redacted/XKCD-password-generator
암호를 생성 할 때 파이썬의 의사 난수 생성기를 신뢰할 수 없습니다. 반드시 암호 학적으로 무작위 일 필요는 없습니다. os.urandom
좋은 시작 인 의사 난수 생성기를 시드하고 있습니다. 그러나 그 후 파이썬 생성기에 의존합니다.
더 나은 선택은와 random.SystemRandom()
같은 소스에서 난수를 가져 오는 클래스입니다 urandom
. 파이썬 문서에 따르면 암호화 사용에 충분해야합니다. 이 SystemRandom
클래스는 메인 랜덤 클래스가하는 모든 것을 제공하지만 의사 난 수성에 대해 걱정할 필요가 없습니다.
random.SystemRandom을 사용하는 예제 코드 (Python 2.6 용) :
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 가용성은 운영 체제에 따라 다릅니다.
귀하의 의견을 고려하여
머릿속에서 떠 올릴 것보다 더 안전한 암호를 생성 할 수 있으면됩니다.
단지 연습으로 작성하는 것이 아니라 프로그램을 사용하여 암호를 생성하려는 것 같습니다. 실수하면 출력이 손상 될 수 있으므로 기존 구현을 사용하는 것이 좋습니다. 난수 생성기 공격 에 대해 읽어보십시오 . 특히 데비안의 잘 알려진 RNG 버그가 사람들의 SSL 개인 키를 노출했습니다.
따라서 대신 pwgen
. 암호를 사용할 대상에 따라 선택해야하는 몇 가지 옵션을 제공합니다.
Implenting @Thomas Pornin 솔루션 : (@Yossi 부정확 한 답변을 주석 할 수 없음)
import string, os
chars = string.letters + string.digits + '+/'
assert 256 % len(chars) == 0 # non-biased later modulo
PWD_LEN = 16
print ''.join(chars[ord(c) % len(chars)] for c in os.urandom(PWD_LEN))
쉽습니다 :)
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()
감사합니다 http://xkcd.com/936/
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()
- 숫자, 대문자, 문자 추가와 같은 실제 규칙을 처리합니다.
물론 개선 할 수 있지만 이것이 제가 사용하는 것입니다.
그 방법이 작동합니다. 완벽합니다. 사전 단어 제외와 같은 추가 규칙이있는 경우 해당 필터도 포함 할 수 있지만 해당 설정으로 사전 단어를 무작위로 생성 할 가능성은 매우 적습니다.
구현에 몇 가지 문제가 있습니다.
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
적어도 대부분의 유닉스 나 시스템에, 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
저는 언어학을 좋아합니다. 저의 접근 방식에서는 자음과 모음을 번갈아 가며 높은 수준의 엔트로피로 기억에 남는 의사 단어를 만듭니다.
- 사전 공격에 취약하지 않음
- 발음 가능하므로 기억에 남을 좋은 기회
- 적절한 강도의 짧은 암호
- 호환성을 위해 임의의 숫자를 추가하는 선택적 매개 변수 (기억하기는 어렵지만 이전 비밀번호 보안 사고로 빌드 된 앱을 준수합니다 (예 : 숫자 필요))
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'
단점 :
- 라틴어 및 게르만어 사용자 및 영어에 익숙한 사용자
- 응용 프로그램 사용자 또는 포커스 그룹이 우세한 언어의 모음과 자음을 사용하고 조정해야합니다.
여기에 또 다른 구현 (파이썬 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 조 개의 추측 (즉, 100TH / s)을 가정하면 더 짧은 버전을 해독하는 데 약 5 천만 ~ 6 천만 년이 걸립니다. 전체 CHBS = 1 조 2,400 억 조 세기; 여기에 패딩을 더하면 15 조 5,100 억 조 조 세기가됩니다.
전체 비트 코인 채굴 네트워크 (이 글을 쓰는 시점에서 ~ 2500 TH / s)를 등록하더라도, 짧은 버전은 여전히 2 억 5 천 ~ 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)`
This will generate a random password with 1 random uppercase letter, 3 random lowercase letters, 3 random digits, and 1 random special character--this can be adjusted as needed. Then it combines each random character and creates a random order. I don't know if this is considered "high quality", but it gets the job done.
Base64 let us encode binary data in a human readable/writable mode with no data loss.
import os
random_bytes=os.urandom(12)
secret=random_bytes.encode("base64")
My solution based on @Thomas Pornin's answer (Updated)
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())
This function returns a random password (without a number or a symbol in beginning of the password).
I just recently started learning python and this is something I wrote today. Hope this helps.
import random
characters = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^()}{/<>'
print('Password Length: ')
passwordLength = int(input())
password = ''
for i in range(passwordLength):
password += random.choice(characters)
print(password)
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]
참고 URL : https://stackoverflow.com/questions/7479442/high-quality-simple-random-password-generator
'code' 카테고리의 다른 글
달력에 대한 날짜 개체 [자바] (0) | 2020.11.14 |
---|---|
실수로 푸시 된 커밋 : git 커밋 메시지 변경 (0) | 2020.11.14 |
matplotlib에서 빈 서브 플롯을 어떻게 만들 수 있습니까? (0) | 2020.11.14 |
명령 줄에서 PHP 스크립트 실행 (0) | 2020.11.14 |
많은 sass 파일을 포함하는 전체 디렉토리 / 폴더의 변경 사항을 보는 방법 (0) | 2020.11.14 |