Last active
May 17, 2017 13:59
-
-
Save sekika/89338aa1a25aebcf2e8698aad6db0080 to your computer and use it in GitHub Desktop.
パスワード生成プログラム
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
# パスワード生成プログラム | |
# | |
# このプログラムに関する記事「パスワードの管理について」 | |
# https://sekika.github.io/2017/05/09/Password/ | |
# | |
# 使い方:プログラムのソースコードに直接サイト情報を書く。 | |
# サイト情報は、サイト名、ハッシュ関数、文字種、文字数、パスワードの種の5つ。 | |
# 引数にサイト名を指定して起動、あるいは起動してからサイト名を指定する。 | |
# マスターパスワードを入力すると、それに対応したパスワードが表示される。 | |
# まずはサイト情報を辞書オブジェクトとして定義する。 | |
# たとえば、 | |
# "google" : ["sha512", "an", 16, "kKkMqYDUIivWLi3WSt3VndHci"], | |
# の行は、サイト名 google のパスワードはsha512 のハッシュ関数を使い、 | |
# an の文字種(アルファベットと数字)で16文字のパスワードを | |
# kKkMq... をサイト固有のパスワードの種として生成する。 | |
# 初期設定のままで google のパスワードをマスターパスワードを空にして生成すると | |
# gak7f1WDmk4jhKRd となる。 | |
# JavaScript 版はこちら | |
# http://seki.webmasters.gr.jp/password.html | |
# Python 版と同じようなサイト情報の設定形式を使い、同じパスワードが生成される | |
# ただし、文字種 ans95 は未対応 | |
sitekey = { | |
"google" : ["sha512", "an", 16, "kKkMqYDUIivWLi3WSt3VndHci"], | |
"amazon" : ["sha3_384", "an", 16, "stBuQIQgT9Yp84RBK3HdllnUK"], | |
"twitter" : ["sha3_512", "an", 14, "UmhvSHT72smO4aI1LMYt7H2el"] | |
} | |
# サイト情報の定義終了 | |
##### メインプログラム開始 ##### | |
import hashlib, base64 | |
import sys, re, getpass | |
# クリップボードを使うときには、次の行をコメントアウト。 pip3 install clipboard が必要。 | |
# import clipboard | |
# サイトをコマンドライン引数から読み込む。引数がなければ入力させる。 | |
if (len(sys.argv)) == 1: | |
for key in sitekey.keys(): | |
print (key) | |
site=input ('サイトを指定してください。') | |
else: | |
site = sys.argv[1] | |
# サイト情報がなければエラーを返して終了する。 | |
if site not in sitekey: | |
print ('サイト {0} は定義されていません。'.format(site)) | |
sys.exit() | |
# サイト情報とマスターパスワードから、パスワードの種となる情報を得る。 | |
site = sitekey[site] | |
has = site[0] # ハッシュ関数の種類 | |
char = site[1] # パスワードで使う文字の種類 | |
plen = site[2] # パスワードの長さ | |
# サイト情報に必須項目以上の要素がある場合には、それをすべて表示する。 | |
# サイトのユーザーIDなどの情報を入れておくと良い。 | |
for i in range(4,len(site)): | |
print (site[i]) # コメント情報を表示 | |
# マスターパスワードを入力させる。 | |
master = getpass.getpass('マスターパスワードを入力してください。') | |
# master = input('マスターパスワードを入力してください。') | |
# マスターパスワード + サイト固有のパスワードの種 | |
seed = (master + site[3]).encode('utf-8') | |
# 指定されたハッシュ関数を適用する。 | |
# ハッシュ関数を統一せずにサイトごとに指定しているのは、パスワードを更新するときに | |
# ハッシュ関数をより新しいものへとアップデートしやすくするためである。 | |
# Python 3 の hashlib ドキュメントは | |
# https://docs.python.jp/3/library/hashlib.html | |
if has == ('sha384'): | |
h = hashlib.sha384(seed) | |
elif has == ('sha512'): | |
h = hashlib.sha512(seed) | |
elif has == ('sha3_384'): | |
h = hashlib.sha3_384(seed) | |
elif has == ('sha3_512'): | |
h = hashlib.sha3_512(seed) | |
else: | |
print ('ハッシュ関数 {0} は定義されていません。'.format(has)) | |
sys.exit() | |
# 指定された文字の種類にしたがって、パスワードの文字列を作る。 | |
# 文字の種類をサイトごとに指定することで、パスワード文字の種類に特殊な | |
# 要求がある場合に対応する。 | |
base = base64.b64encode(h.digest()).decode("utf-8") # base64 エンコード | |
if char == ('base64'): # base64: アルファベット、数字、+/ | |
p = base | |
elif char == ('an'): # an: アルファベットと数字 | |
p = re.sub(r'[+/=]',"", base) | |
elif char == ('a'): # a: アルファベットのみ | |
p = re.sub(r'[0-9+/=]',"", base) | |
elif char == ('n'): # n: 数字のみ | |
p = re.sub(r'[a-f]',"", (h.hexdigest())) | |
elif char == ('ans'): # ans: アルファベットと数字と記号 | |
symbol = '#[$-=?@]_!' # + と / 以外で使用可能な記号 | |
p = base.replace('=','') | |
a = ord(p[0:1]) % len(symbol) | |
symbol = symbol[a:-1] + symbol[0:a] # 記号の発生確率を均等に | |
for s in symbol: | |
p = p.replace(p[0:1], s)[1:-1] + p[0:1] | |
elif char == ('ans95'): # ans95: アルファベットと数字と記号全95種類 (JavaScript 版未対応) | |
h = int.from_bytes(h.digest(), byteorder='big') | |
p = '' | |
for i in range(plen): | |
p = p + chr(h % 95 + 32) | |
h = h // 95 | |
else: | |
print ('文字種 {0} は定義されていません。'.format(char)) | |
sys.exit() | |
# 指定された長さのパスワードを表示する。 | |
print (p[0:plen]) | |
# クリップボードにコピーするときには、次の2行をコメントアウト。 | |
# clipboard.copy(p[0:plen]) | |
# print ('パスワードをクリップボードにコピーしました。') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
このプログラムに関する記事「パスワードの管理について」(一般向け)
https://sekika.github.io/2017/05/09/Password/
Qiita の記事(プログラマー向け)
http://qiita.com/sekik/items/37e283f527301ec50c98