Python学習【365日チャレンジ!】238日目のマスターU(@Udemy11)です。
ネットの広告に出てきた「年間120時間の時短を実現した50のテクニック 脱マウス最速仕事術」を9月頭に購入して実践しているところですが、どうしても右手がマウスに言ってしまいます。
MacBookProを使うときは普通にタッチパッドに親指や中指がいってしまうんですよね。
あと、Pycharmでは、vimを使ってコードを打つようにしているのですが、インサートモード、ノーマルモード、ビジュアルモードの使い分けがいまいちうまくできません。
プログラマーではないので、圧倒的に使用頻度が少ないため、キーの役割をいちいち考えてしまうので、ブラインドタッチのように操作することができていません。
vimは、技術習得までのラーニングコストが高いといわれているので、そんな簡単にマスターできるとは考えていませんが、操作に慣れるまでにちょっと時間がかかりそうです。
どうしても今までやっていた方法が一番操作しやすいので、そちらに逃げてしまい、結局vimを使うのを挫折する人がいるのもうなずけます。
vimをマスターするには、かなり苦労すると思いますが、vimを自在に操れるPythonマスター目指して使い続けたいとおもいます。
昨日の復習
昨日は、hashlib
を使った暗号化を学習しました。
hashlib
を使って任意の文字列をハッシュ化してシステムのログインに使いましたが、ハッシュ化は暗号化と違い、ハッシュ値から元の値に復元する復号化ができないのが特徴でした。
文字列から作られるハッシュ値は、元の値が同じならハッシュ値も同じになるので、対応表があれば復元可能でした。
詳細については、昨日の記事をごらんになってみてください。
今日は、hashlib
を使ったよりセキュリティの高い暗号化を学習します。
salt
昨日学習したように、任意の文字列のパスワードから作られるハッシュ値は、もとの値が同じなら、同じハッシュ値になるので、ありとあらゆる値をハッシュ化した対応表があれば、ハッシュ値からパスワードがわかってしまいます。
そこで使われるのが、元のパスワードにランダムな文字列を付け足してハッシュ化する方法です。
この方法だと、万が一データベースが漏洩してしまったとしても、ハッシュ値から元の値が解読できたとしても、その値はパスワードじゃないので、単純なハッシュ化よりもセキュリティーが高くなります。
それがsalt
というもので、元のパスワードの前か後ろに付け足してハッシュ化します。
import base64
import os
import hashlib
user_name = 'user1'
user_pass = 'zyxabcde'
db = {}
salt = base64.b64encode(os.urandom(32))
print(salt)
def get_digest(password):
password = bytes(user_pass, 'utf-8')
digest = hashlib.sha256(salt + password).hexdigest()
return digest
db[user_name] = get_digest(user_pass)
def is_login(user_name, password):
return get_digest(password) == db[user_name]
print(db)
print(is_login(user_name, user_pass))
ハイライトしているprint
出力は、salt
、db
に何が入っているのかわかるように出力しています。
最初にsalt
のランダムな値を作るためにbase64
とos
をインポートします。
9行目は、salt
を作成するときの定番のコードなので、覚えておいて損はありません。
作成したsalt
は、15行目のハッシュ値digest
を作成する際に、password
に付け足して使います。
生成したハッシュ値を18行目でuser_name
のvalue
に代入します。
あとのコードは昨日と同じで、db
に保存された値とuser_name
とuser_pass
を照らし合わせてTrue
かFalse
を返しています。
出力結果
b'pinbUUFOgQPTSG/rNHGeF8ZgZN+7eELXsmwjm3vyejU='
{'user1': '502e946cc1ed08d7eea9944a81957295edf3428cc21ff01cb3eaf55ccd5e1b94'}
True
このコードの場合、db
に保存した際のsalt
と仮のログインで参照するsalt
が同じなので、結果はTrue
になっています。
実際は、データベースにuser_name
とハッシュ化されたuser_pass
を保存する段階で、生成されたsalt
も同じデータベースか他のデータベースに保存しておく必要があります。
でないと、ログインの際に、ハッシュ値が違ったものになってしまいますので、注意が必要です。
stretching
salt
を使ったハッシュ化は、ハッシュ化のみよりもセキュリティーが高まりますが、データベースに保存したsalt
も一緒に漏洩してしまうと、パスワードが解読される可能性があります。
そこで登場するのがハッシュ化を複数回繰り返してハッシュ値を生成するストレッチングです。
for
ループを任意の回数繰り返してハッシュ値を作るので、この値を復元するのは不可能に近くなります。
def get_digest(password):
password = bytes(user_pass, 'utf-8')
digest = hashlib.sha256(salt + password).hexdigest()
for _ in range(10000):
digest = hashlib.sha256(bytes(digest, 'utf-8')).hexdigest()
return digest
13行目の関数に16行目、17行目のfor
ループのコードを付け足しています。
password
にsalt
を付け加えて作成したdigest
を元にfor
ループで10000回ハッシュ化した値に変更しています。
ストレッチングによって、ハッシュ値からハッシュを作るという作業を10000回も実行しているので、ハッシュ値が漏洩したとしても元の値を求めるにはほぼ不可能に近くなります。
まとめ
守る側と盗む側のやり取りは、基本的にいたちごっこです。
守る側はあらゆる攻撃に備えないといけませんが、盗む側は一つ穴を見つければそこから攻めることができます。
当然、守る側より盗む側(攻める側)のほうが有利ですし、攻めるほうは守るものがないので、捨て身で攻撃することができます。
守る側は、すべての穴を塞げるわけではないので、可能な限り攻撃に備えないといけませんが、コストも膨れ上がるので、セキュリティーと費用対効果のトレードオフになるのが現状です。
プログラマー側としては、できる限りのセキュリティー対策はしっかりとやっておかないといけないので、ハッシュ化や暗号化・復号化についてはしっかりと学習しておきましょう。
それでは明日もGood Python!