ランダム(Rnd)関数を使って辞書攻撃にも対応したパスワードジェネレーターをつくってみよう。

中級者

まえがき

ランダム(Rnd)関数とは、乱数をつかって数値を変動させるもので、ゲームで言うと、会心の一撃で攻撃力が倍になったり、通常攻撃でもダメージが上下するような動きをさせるために使われています。

ランダム関数なんて使い道ないんじゃないの~

ねこ
ねこ

くらえ!会心の肉球~!!!

ぐあ~~~~~~~

ゲーム以外ではどのような使い道があるのかと言われた時、使い方を思いつかなかったのですが、パスワードを自動生成させるツール(パスワードジェネレーター)を作れるという事に気が付きました。

今回はRandomize関数を使って、パスワードジェネレーターを作成する方法を解説したいと思います。

また本記事で解説したパスワードジェネレーターはこちらから無償配布します。全コード下記で開示していますし、改造や二次配布も自由にして頂いて構いません。

ランダム(Rnd)関数の基本動作

Rnd関数の使い方はRndと書くだけです。Rndと書いたところが0~0.999999999までの小数点以下最大9桁の数値として扱われます。

forを使った繰り返しで10個のランダムな数値を出力させてみます。

For i1 = 1 To 10
Cells(i1 + 8, 6) = Rnd
Next i1

結果はこのようになります。

この結果を一つ右側の列に移動させて、ファイルを保存し、再度ファイルを開き直してマクロを実行するとこのような結果となりました。

右が1回目に作成した数値で、左が2回目に作成した数値です。見ての通り全く同じ値が作成されています。

理由は、Rnd関数がシード値を元に乱数を作成していて、Excelを起動した時に毎回同じシード値となる事から、同じ順番で数値が作成されます。

この乱数を作成する元となるシード値をランダムにするためには、Randomizeを使用する必要があります。

先ほどのコードの頭にRandomizeを追加します。

Randomize
For i1 = 1 To 10
Cells(i1 + 8, 6) = Rnd
Next i1

[ファイル開く➡マクロ実行➡ファイル閉じる]の繰り返しを3回追加で実施してみた結果がこちらです。

一番右が最初に作成したもので、2~4回目はそれぞれ別の数字となった事が分かります。これで完全なランダム値の完成です。

Rnd関数の使い方

Rnd関数は0~0.999999999の間の数値しかとりませんので、それ以外の数字にしたい場合は工夫が必要です。

最大値と最小値の整数を取得する場合

最大値と最小値を変更して、整数値(Int)を取得する場合は、このように記載します。

Int((最大値最小値 + 1) * Rnd) + 最小値

例えば最大値が30で最小値が15の場合は

Int((30 – 15 + 1) * Rnd) + 15
Int(16 * Rnd) + 15

となります。

Rndが最大値0.999999999の時、[16 * Rnd]は15.999999984となります。Intで切り捨てられて[Int(16 * Rnd) ]は15になります。それに15を足すので最大30となります。

Rndが最小値0の時、[16 * Rnd]は0となります。それに15を足すので最小15となります。

ランダムな英語の小文字を取得する

ランダムな英語の小文字を取得するには以下のように記載します。

komoji = “abcdefghijknmprstuvwxyz”
        Randomize
        str2 = Mid(komoji, Int(23 * Rnd) + 1, 1)

komojiに選択させたい文字(23文字)を入れています。lは数字の1と見間違えやすく、oは数字の0と、qは数字の9と見間違いやすいのでわざと外しています。

Mid関数を使って、komojiから[Int(23 * Rnd) + 1]番目の文字を1文字取得します。

[Int(23 * Rnd) + 1]は1~23までの整数となるので、23文字文字の内の1文字がランダムで選ばれます。

パスワードジェネレーター機能解説

まずは、作成したパスワードジェネレーターの機能解説をしていきます。

設定画面がこのようになっています。

一番上の文字数のところに、作成したいパスワードの文字数を入力します。

文字数はExcelのデータの入力規則の制限で9~1000文字で指定できるようになっています。

次に個数は、パスワードを作成する個数です。1~1000個まで作成できます。こちらも入力規則の制限で決められた文字しか入力できないようにしています。

取り除く文字は下の[②文字 取り除き実施]ボタンと連携しています。

作成したパスワードの中から、入って欲しくない文字を取り除きます。例えば、機器側の制約で$が使えない場合は、ここに$を入れて、[②文字 取り除き実施]ボタンをクリックする事で、$を取り除きます。

[①パスワード作成]ボタンでパスワードを作成します。パスワード生成ルールは下記に記載します。

フリガナが欲しい時は[③パスワードフリガナ記載]ボタンをクリックして下さい。ボタンを押した時の文字に合わせたフリガナを作成します。

[全消]ボタンで発行したパスワードの数だけA列とB列を空白に戻します。

パスワード作成ルール

パスワード作成機能は、以下ルールで作成されます。8文字毎に別シートの3000語の辞書でチェックをして、辞書攻撃を食らいにくいように考慮しています。

また、キーボードの配列攻撃も考慮して、隣り合うキーが連続しないように配慮しています。

  1. 1文字目を英文字から選択
  2. 2文字目を上1行を除いた英文字から選択(数字と隣り合う文字はキー配列が並ぶ可能性があるため)
  3. 3文字目を数字から選択
  4. 4文字目を上1行を除いた英文字から選択(数字と隣り合う文字はキー配列が並ぶ可
    能性があるため)
  5. 5文字目を上1行を除いた英文字から選択(数字と隣り合う文字はキー配列が並ぶ可
    能性があるため)
  6. 6文字目を数字から選択
  7. 7文字目を上1行を除いた英文字から選択(数字と隣り合う文字はキー配列が並ぶ可能性があるため)
  8. 8文字目を英文字から選択
  9. 1文字目と8文字目のどちらか1つを大文字に変更(パターンを増やし、大文字必須のシステムに対応するため)
  10. 英文字6文字内に英語辞書シート(3~6文字)のものが含まれていないことをチェックする(同じ文字6文字の場合もやり直す)文字数に応じて①~⑩を繰り返す。

マクロ解説

マクロを解説してきます。配列の部分は別記事としたいので、ここでは解説を省略します。

[①パスワード作成]ボタン

メインのパスワードgeneratorの部分のマクロです。

途中途中でRandomizeが入っていますが、最初に1回だけでも良いです。

str1 = UCase(str2)で小文字を大文字に変換しています。それ以外はパスワード生成ルールの通り英子文字、英子文字の中段と下段、数字を組み合わせたり、ランダムに1文字目か8文字目を大文字に変えたりしてます。

8文字作り終わったら、辞書と一致していないかチェックして、一致した場合はmouichidoに戻してループさせています。

8文字ずつ作って、指定された文字数に達しているかチェックして、足りない場合は、もう一セット実施します。文字数をオーバーしている場合は、Left関数で丁度の文字数に調整しています。

Sub パスワードジェネレータ()
    Dim komoji As String, komoji1 As String, str1 As String
MOJISUU = Cells(3, 2) ‘パスワードの文字数
KOSUU = Cells(4, 2) + 7 ‘パスワードの発行数
For i4 = 8 To KOSUU
MOJISUUCHK:
mouichido:
    komoji = “abcdefghijknmprstuvwxyz”
    komoji1 = “asdfghjkzxcvbnm”
    suuji = “2345678”
    kigou = “#$%&=@”
        Randomize
        n1 = Int(10 * Rnd + 1)
        Randomize
        str2 = Mid(komoji, Int(23 * Rnd) + 1, 1)
        If n1 < 6 Then ‘n1が6未満の場合は1文字目を大文字に変更する
        str1 = UCase(str2)
        Else
        str1 = str2 ‘str1はパスワード
        End If
        str3 = str2 ‘str3は英語辞書チェック用のワード
    For i2 = 1 To 2
        Randomize
        n = Int(15 * Rnd + 1) ‘2,5文字目を上1行を除く英字から選択
        str2 = Mid(komoji1, n, 1)
        str1 = str1 & str2
        str3 = str3 & str2
        Randomize
        n = Int(7 * Rnd + 1) ‘3,6文字目は数字
        str2 = Mid(suuji, n, 1)
        str1 = str1 & str2
        Randomize
        n = Int(15 * Rnd + 1) ‘4,7文字目を上1行を除く英字から選択
        str2 = Mid(komoji1, n, 1)
        str1 = str1 & str2
        str3 = str3 & str2
    Next i2
        Randomize
        n = Int(23 * Rnd + 1) ‘8文字目を英字から選択
        str2 = Mid(komoji, n, 1)
        If n1 > 5 Then ‘n1が5より大きい場合は8文字目を大文字に変更する
        str1 = str1 & UCase(str2)
        Else
        str1 = str1 & str2
        End If
        str3 = str3 & str2
        Randomize
        n = Int(6 * Rnd + 1)  ‘9文字目に記号を追加
        str2 = Mid(kigou, n, 1)
        str1 = str1 & str2
‘辞書シートを使ってチェックを行い、問題がある場合は「もう一度(mouichido)」へ戻る
MaxRow2 = Sheets(“英語辞書”).Cells(Rows.Count, 2).End(xlUp).Row ‘MaxRowは最終行
For i5 = 1 To MaxRow2
 If str3 Like “*” & Sheets(“英語辞書”).Cells(i5, 2) & “*” Then
 GoTo mouichido
 End If
Next i5
Cells(i4, 1) = Cells(i4, 1) & str1
If Len(Cells(i4, 1)) >= MOJISUU Then
Cells(i4, 1) = Left(Cells(i4, 1), MOJISUU)
Else
GoTo MOJISUUCHK
End If
Next i4
End Sub

[②文字 取り除き実施]ボタン

KOSUU = Cells(4, 2) + 7 で発行したパスワードの最終行を取得します。

Forで最終行まで繰り返します。

Replace関数でCells(5, 2)に指定した文字を空(””)に置き換えて、削除します。

Sub 文字取り除き()
KOSUU = Cells(4, 2) + 7 ‘パスワードの発行数
For i4 = 8 To KOSUU
Cells(i4, 1) = Replace(Cells(i4, 1), Cells(5, 2), “”)
Next i4
End Sub

[③パスワードフリガナ記載]ボタン

strTargetにすべての文字を格納します。

strYomiにすべてのフリガナを コンマ(,) 区切りで格納します。

配列の詳細は別記事で記載しますが、簡単に説明すると配列を使って、前の文字から1文字ずつフリガナに書き換えて半角スペースを入れています。

Sub 英数字フリガナ()
    Dim strTarget$, strYomi$, strTmp$, Buf$
    Dim rngCurrent     As Range
    Dim aryYomi(42, 1) As String
    Dim tmp
    Dim i As Long, j   As Long
    strTarget = “0123456789abcdefghijklmnopqrstuvwxyz#$%&=@”
    strYomi = “ゼロ,イチ,ニ,サン,ヨン,ゴ,ロク,ナナ,ハチ,キュウ,”
    strYomi = strYomi & “エイ,ビー,シー,ディ,イー,エフ,ジー,エイチ,アイ,ジェイ,”
    strYomi = strYomi & “ケイ,エル,エム,エヌ,オウ,ピー,キュウ,アール,エス,ティ,”
    strYomi = strYomi & “ユウ,ブイ,ダブリュ,エックス,ワイ,ゼット,”
    strYomi = strYomi & “シャープ,ドル,パーセント,アンド,イコール,アット”
    tmp = Split(strYomi, “,”)
    MaxRow = Cells(Rows.Count, 1).End(xlUp).Row ‘MaxRowは最終行
    For n1 = 8 To MaxRow
    Cells(n1, 1).Select
    For i = 1 To 42
        aryYomi(i – 1, 0) = Mid(strTarget, i, 1)
        aryYomi(i – 1, 1) = tmp(i – 1)
    Next i
    For Each rngCurrent In Selection
        If Not IsEmpty(rngCurrent) Then
            Buf = CStr(Trim(rngCurrent.Value))
            Buf = StrConv(Buf, vbNarrow)
            Buf = StrConv(Buf, vbLowerCase)
            strYomi = “”
            For i = 1 To Len(Buf)
                strTmp = Mid(Buf, i, 1)
                For j = 1 To 42
                    If strTmp = aryYomi(j – 1, 0) Then
                        strYomi = strYomi & aryYomi(j – 1, 1) & ” “
                        Exit For
                    End If
                Next j
            Next i
            rngCurrent.Characters.PhoneticCharacters = Trim(strYomi)
        End If
    Next rngCurrent
    Cells(n1, 2) = strYomi
    Next n1
End Sub

[全削]ボタン

KOSUU = Cells(4, 2) + 7 で発行したパスワードの最終行を取得します。

RangeコマンドでA列、B列の対象範囲を空(””)します。

Sub 全削除()
KOSUU = Cells(4, 2) + 7
Range(Cells(8, 1), Cells(KOSUU, 2)) = “”
End Sub

あとがき

Rnd関数の部分だけは理解いただけたでしょうか?

このように1つのツールを作成するためには、複数の知識が必要になります。

構文丸暗記する必要はありませんが、マクロの作成経験を積んで自身の引き出しを増やしておけば、こういったひらめきが出来るようになりますので、どんどん手を動かして作ってみて下さい。

私自身に言える事ですが、やりたい事があって、それを実現する手段を調べて、その手段をどのように組み合わせて動作させれば良いかパーツに分解して設計して、設計する事の繰り返しが、上達のコツだと思います。

また、私がこの記事を記載しているのも、自身の知識だけでなく、記事を書くために追加で調べた事も整理する事で、より洗練されたプログラムを作成する手助けになると思っています。

Copy Protected by Tech Tips's CopyProtect Wordpress Blogs.
タイトルとURLをコピーしました