超速で実装だ!C#でランダムな文字列のパスワードを生成する

2021年6月2日水曜日

C#

t f B! P L

この記事では、C#でランダムなパスワードを生成するサンプルコードを紹介します。

スポンサーリンク

数値のみのランダムなパスワード

Randomクラスを使って、数値のみのランダムなパスワードを生成します。

Linqを使えば、次のような感じでシンプルに書けます。

Random rng = new Random();
string password = string.Join("",
Enumerable.Range(0, 10).Select(n => rng.Next(0, 9).ToString())
);
Console.WriteLine(password);  //-> 7821867520s

記号・英字・数字を1つ以上含むパスワードを生成

パスワードの要件によっては、複数の文字種をそれぞれ最低でも1つ以上含める必要があるケースもあります。

次のサンプルコードは、少なくとも数字、大文字、小文字および記号を1文字以上含むランダムなパスワードを生成する例です。コピペして使えるようにクラス形式のサンプルコードにしています。

using System;
using System.Linq;

static class RandomPassword
{

    private const string ASCII_NUMBER = "0123456789";                       //数字
    private const string ASCII_UPPER_ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";  //英字大文字
    private const string ASCII_LOWER_ALPHA = "abcdefghijklmnopqrstuvwxyz";  //英字小文字
    private const string ASCII_MARK = "!\"#$%&'()*+-/<=>?@;[]^";            //記号

    private static readonly Random rng = new Random(); //ランダムクラス

    /// <summary>
    /// ランダムな文字列を生成する。
    /// </summary>
    /// <param name="length">文字列の長さ</param>
    /// <returns>数字、大文字、小文字および記号を1文字以上含むランダムな文字列</returns>
    public static string Generate(int length)
    {
        string allSource = ASCII_NUMBER + ASCII_UPPER_ALPHA + ASCII_LOWER_ALPHA + ASCII_MARK;

        //各文字種を最低1文字含める
        string password = Choice(ASCII_NUMBER)
                        + Choice(ASCII_UPPER_ALPHA)
                        + Choice(ASCII_LOWER_ALPHA)
                        + Choice(ASCII_MARK);

        //任意の文字種でランダムな文字を生成
        int cnt = length - password.Length;
        for (int i = 0; i < cnt; i++)
        {
            password += Choice(allSource);
        }

        //生成した文字列をシャッフルして返す
        return string.Join("", password.OrderBy(n => rng.Next()));
    }

    /// <summary>
    /// 指定された文字列ソースからランダムに1文字選択する
    /// </summary>
    /// <param name="source">文字列ソース</param>
    /// <returns>ランダムに選択した文字</returns>
    private static string Choice(string source)
    {
        return source[rng.Next(0, source.Length - 1)].ToString();
    }
}

■ 実行結果

上のサンプルコードを、RandomPassword.Generate(10)のようにして呼び出すと、10文字のランダムなパスワードを生成します。

apM3>Mvo5u

Randomクラスはスレッドセーフではない

ランダムなパスワードや乱数の生成などに用いられるRandomクラスですが、このクラスはスレッドセーフではありません。

また、スレッドセーフではないからと言って、乱数を生成する度にRandomクラスのインスタンスを作成すると、同一の数値シーケンスを生成する乱数ジェネレーターが作成され、結果的に同じパスワードが生成される恐れがあります。

Webアプリなどのマルチスレッド環境では、C#だったらLock、Visual BasicならSyncLockステートメントを使って、複数のスレッドがRandomクラスのインスタンスにアクセスできないように制御します。

スポンサーリンク

QooQ