ブルートフォース攻撃に強いパスワードの作り方

今回はブルートフォース攻撃に強いパスワードの作り方について書いていきたいと思います。

ブルートフォース攻撃とは、いわゆる総当たり攻撃のことで、1から順番に確かめていけばその内正しいパスワードに行きつくだろう、という、シンプルながら中々強力なパスワード探索方法です。

このような攻撃を受けない(探索されないために)ために、パスワードを強固なものにしたいところですが、その時にどう強くすればいいのかよく分かりませんよね。

  ・使う文字の種類を増やした方が良いの?

  ・それとも文字数を長くした方が良いの?

それについてPytthonでコードを書いて検証をしてみました。

検証では以下の3つの条件で、それぞれランダムにパスワード文字列を作ってブルートフォース攻撃を5回行い、探索にかかった平均時間の比較を行いました。

  条件1:文字は英語小文字(26種類)。長さは5文字

  条件2:文字は英語小文字 + 数字(36種類)。長さは5文字

  条件3:文字は英語小文字(26種類)。長さは6文字

さて、どれが一番探索に時間がかかったでしょう?

その答えを書く前に今回実験で書いたコードを記します。

from itertools import product
import string
import random
import time

random.seed(0)

TYPE_PW = ((0, 5), (1, 5), (0, 6))
CYCLE_REPEAT = 5


def generate_chars(type):
    if (type == 0):
        # 英小文字を取得
        dat = string.ascii_lowercase
    elif (type == 1):
        # 英小文字+数字を取得
        dat = string.ascii_lowercase + string.digits
    else:
        dat = "0"
    return dat


if __name__ == "__main__":
    for type in range(len(TYPE_PW)):
        total_time = 0.0
        chars = generate_chars(TYPE_PW[type][0])
        print("lower         ", end="( ") if TYPE_PW[type][0] == 0 else print("lower + digits", end="( ")
        print(len(chars),  "), pw_num =", TYPE_PW[type][1], end=". ")
        for i in range(CYCLE_REPEAT):
            pw_set = product(chars, repeat=TYPE_PW[type][1])
            pw = ''.join([random.choice(chars) for i in range(TYPE_PW[type][1])])
            start = time.time()
            for word in pw_set:
                if ''.join(word) == pw:
                    break
            end = time.time()
            total_time += (end - start)
        print("TIME(AVG): {:.3f} sec".format(total_time / CYCLE_REPEAT))

このコードの実行結果は以下のようになります

lower         ( 26 ), pw_num = 5. TIME(AVG): 0.995 sec
lower + digits( 36 ), pw_num = 5. TIME(AVG): 5.843 sec
lower         ( 26 ), pw_num = 6. TIME(AVG): 24.233 sec

結果は、長さを6文字にした条件3が最も探索に時間がかかりました。上のコードでは使う文字種類の数が分かっている前提ではあるものの、文字の種類を40%近く増やした条件2が条件3より探索時間が短いのは少し意外ですね!

これより、パスワードを作る時は、とにかく長いパスワードを作る(システム側で言うなら長いパスワードを作れる)方が強固なパスワードだと言えそうですね。

※本当は組み合わせの数をグラフにプロットして理論的な検証も行おうと思いましたが面倒になったのでそれは気が向いたらします!笑