System.Web.Security.Membership.GeneratePassword() の代替 (.NET Coreや.NET 5/6)

System.Web.Security.Membership.GeneratePassword()メソッドは、指定された長さと非英数字文字の数でランダムなパスワードを生成するために使用されます。.NET Coreや.NET 5/6ではSystem.Web.Securityは利用できないため、同等の機能を持つ代替手段を使用する必要があります。

.NET 6でランダムなパスワードを生成するための一般的な方法は、RNGCryptoServiceProviderを使用してランダムなバイト配列を生成し、それを適切な文字セットに変換することです。

以下は、System.Web.Security.Membership.GeneratePassword()に似た機能を持つメソッドのサンプルです:

using System;
using System.Security.Cryptography;
using System.Text;

public static class PasswordGenerator
{
    private static readonly char[] PunctuationChars = "!@#$%^&*()_-+=[{]};:>|./?".ToCharArray();

    public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
    {
        if (length < 1 || length > 128)
        {
            throw new ArgumentException("Password length should be between 1 and 128.");
        }

        if (numberOfNonAlphanumericCharacters > length || numberOfNonAlphanumericCharacters < 0)
        {
            throw new ArgumentException("Number of non-alphanumeric characters should be non-negative and less than password length.");
        }

        using (var rng = new RNGCryptoServiceProvider())
        {
            var byteBuffer = new byte[length];
            rng.GetBytes(byteBuffer);

            var chars = new char[length];
            int nonAlphanumericCount = 0;

            for (int i = 0; i < length; i++)
            {
                int value = byteBuffer[i] % 87;

                if (value < 10)
                    chars[i] = (char)('0' + value);
                else if (value < 36)
                    chars[i] = (char)('A' + value - 10);
                else if (value < 62)
                    chars[i] = (char)('a' + value - 36);
                else
                {
                    chars[i] = PunctuationChars[value - 62];
                    nonAlphanumericCount++;
                }
            }

            for (int i = 0; i < length && nonAlphanumericCount < numberOfNonAlphanumericCharacters; i++)
            {
                int punctuationIndex = byteBuffer[i] % PunctuationChars.Length;
                if (char.IsLetterOrDigit(chars[i]))
                {
                    chars[i] = PunctuationChars[punctuationIndex];
                    nonAlphanumericCount++;
                }
            }

            return new string(chars);
        }
    }
}