概要
DBに保存していたハッシュ化したパスワードが盗まれたら、どのくらいのスピードでパスワードを特定できるのか、簡単なプログラムで試してみたいと思います。
今回作成するプログラムは、赤い枠の部分になります。
セキュリティ用語
総当たり攻撃
総当たり攻撃とは、暗号解読方法のひとつで、可能な組合せを全て試すやり方。攻撃、または片仮名でブルートフォースアタックとも呼ばれる。(出典:Wikipedia)
レインボーテーブル攻撃
レインボーテーブルは、ハッシュから平文を得るために使われるテクニックの一つである。特殊なテーブルを使用して表引きを行う。(出典:Wikipedia)
プログラム
パスワードのハッシュ化
初めにパスワードは以下のルールで作成します。
- 文字数:
5文字
- 使用可能な文字:
abcdefghijklmnopqrstuvwxyz
の27文字
計測は最後の文字列のzzzzz
で作成したいと思います。
暗号化方式は、SHA512で行います。
import hashlib
password = 'zzzzz'
text = hashlib.sha512(password.encode()).hexdigest()
print(text)
下記がzzzzz
をSHA512で暗号化した文字列です。
de2adab3fb5ff37f39a37695a9ddeae600774d1ca00244651c023eb3fa413db1a9454e771db6fad39363dc6fd1c4e5eac2e53a3d86117bed95017b2394b8e4b4
パスワードの特定
import hashlib
import time
import itertools
import string
# 使用可能な文字列(abcdefghijklmnopqrstuvwxyz)
availableStr = string.ascii_lowercase
# パスワード桁数
digit = 5
# 暗号化した文字列
text = 'de2adab3fb5ff37f39a37695a9ddeae600774d1ca00244651c023eb3fa413db1a9454e771db6fad39363dc6fd1c4e5eac2e53a3d86117bed95017b2394b8e4b4'
# 開始時間を記録
startTime = time.time();
attackCount = 0 # 試行回数を保存する
# パスワードを特定
for i in itertools.product(availableStr, repeat=digit):
attackCount += 1
if hashlib.sha512(''.join(i).encode()).hexdigest() == text:
password = ''.join(i)
break
# 処理時間を計測を終了
elapsedTime = time.time() - startTime
print("パスワード:"+ password)
print("試行回数:"+ str(attackCount))
print("処理時間:"+ '{0:.3f}'.format(elapsedTime))
出力結果です
パスワード:zzzzz
試行回数:11881376
処理時間:28.527
パスワード桁数ごとの比較
使用可能文字が27文字だと、パスワード6桁の場合でも15分もあればパスワードを特定できるようです。
桁数 | 試行回数 | 処理時間(秒) |
---|---|---|
3桁 | 17,576 | 0.039 |
4桁 | 456,976 | 1.024 |
5桁 | 11,881,376 | 28.527 |
6桁 | 308,915,776 | 919.719 |
桁数が増えるたびに処理時間が指数的に増えます。
対策
対策① 使用可能文字やパスワード文字列を増やす
今回は、検証時間が長くなってしまうので検証しませんが、「使用可能文字」「パスワード文字列」を増やすことで、特定までに時間がかかります。
対策② ソルトを使用する
ソルトとは、ハッシュ化するときにパスワードの文字列を追加することで、パスワードを特定しにくくします。
対策③ ストレッチングを行う
ストレッチングとは、ハッシュ化した文字列を再度ハッシュ化することで強固なパスワードになります。複数回ハッシュ化することでさらに強固になります。
おわりに
今回は、「パスワードの特定」と「対策」を簡単に説明しました。
プログラムのほうは、「処理の最適化」や「性能の良いPCで実施」することで処理時間を速くすることができると思います。
どんどんセキュリティ対策を強化していきましょう!
ここまで見ていただきありがとうございました。