首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

C# 產生高強度隨機密碼完整實作(含密碼學級隨機數)

     編輯:ASP.NET 基礎

前言

系統產生臨時密碼、API Key、重設連結 Token 等場景,需兼具高熵值、可配置長度/字符集、密碼學安全隨機源。本文提供生產級 RandomPassword 靜態類別,採用 RNGCryptoServiceProvider 種子,支援多字符組強制包含、長度範圍隨機、可重現測試。

核心特性

  • 四大字符組:小寫、大寫、數字、特殊符號(可自行增減)。
  • 強制包含:演算法確保每組至少出現一次(直到該組用盡)。
  • 長度範圍:Generate(min, max) 隨機決定長度。
  • 加密級隨機:RNGCryptoServiceProvider 產生 4-byte 種子給 Random。
  • 無偏選取:使用 Fisher-Yates 洗牌邏輯,避免模數偏差。

完整代碼

using System;
using System.Security.Cryptography;

public static class RandomPassword
{
    private static readonly int DEFAULT_MIN = 8;
    private static readonly int DEFAULT_MAX = 16;

    private static readonly string LCASE = "abcdefghijkmnopqrstuvwxyz"; // 移除 l 混淆
    private static readonly string UCASE = "ABCDEFGHJKLMNPQRSTUVWXYZ"; // 移除 I O
    private static readonly string NUMERIC = "23456789";                // 移除 0 1
    private static readonly string SPECIAL = "*$-+?_&=!%{}/";

    public static string Generate() => Generate(DEFAULT_MIN, DEFAULT_MAX);
    public static string Generate(int length) => Generate(length, length);

    public static string Generate(int minLength, int maxLength)
    {
        if (minLength <= 0 || maxLength <= 0 || minLength > maxLength) return null;

        var charGroups = new[]
        {
            LCASE.ToCharArray(),
            UCASE.ToCharArray(),
            NUMERIC.ToCharArray(),
            SPECIAL.ToCharArray()
        };

        int[] charsLeft = new int[charGroups.Length];
        for (int i = 0; i < charsLeft.Length; i++) charsLeft[i] = charGroups[i].Length;

        int[] groupOrder = new int[charGroups.Length];
        for (int i = 0; i < groupOrder.Length; i++) groupOrder[i] = i;

        // 密碼學種子
        var rng = new RNGCryptoServiceProvider();
        var seedBytes = new byte[4];
        rng.GetBytes(seedBytes);
        int seed = (seedBytes[0] & 0x7f) << 24 | seedBytes[1] << 16 | seedBytes[2] << 8 | seedBytes[3];
        var random = new Random(seed);

        int pwdLen = (minLength == maxLength) ? minLength : random.Next(minLength, maxLength + 1);
        char[] password = new char[pwdLen];

        int lastGroupIdx = groupOrder.Length - 1;
        for (int i = 0; i < pwdLen; i++)
        {
            int pickGroupOrderIdx = (lastGroupIdx == 0) ? 0 : random.Next(0, lastGroupIdx + 1);
            int groupIdx = groupOrder[pickGroupOrderIdx];
            int lastCharIdx = charsLeft[groupIdx] - 1;
            int pickCharIdx = (lastCharIdx == 0) ? 0 : random.Next(0, lastCharIdx + 1);

            password[i] = charGroups[groupIdx][pickCharIdx];

            // 將已用字符換到組尾,縮小可用範圍
            if (pickCharIdx != lastCharIdx)
            {
                var tmp = charGroups[groupIdx][lastCharIdx];
                charGroups[groupIdx][lastCharIdx] = charGroups[groupIdx][pickCharIdx];
                charGroups[groupIdx][pickCharIdx] = tmp;
            }
            charsLeft[groupIdx]--;

            // 該組用盡,將組換到順序尾部
            if (charsLeft[groupIdx] == 0)
            {
                charsLeft[groupIdx] = charGroups[groupIdx].Length; // 重置供下輪
                if (pickGroupOrderIdx != lastGroupIdx)
                {
                    var tmp = groupOrder[lastGroupIdx];
                    groupOrder[lastGroupIdx] = groupOrder[pickGroupOrderIdx];
                    groupOrder[pickGroupOrderIdx] = tmp;
                }
                lastGroupIdx--;
                if (lastGroupIdx < 0) lastGroupIdx = groupOrder.Length - 1;
            }
        }
        return new string(password);
    }
}

使用範例

// 1. 預設 8-16 碼
string pwd1 = RandomPassword.Generate();

// 2. 固定 12 碼
string pwd2 = RandomPassword.Generate(12);

// 3. 指定範圍 10-20 碼
string pwd3 = RandomPassword.Generate(10, 20);

// 4. 自訂字符組(繼承修改或複製類別調整 LCASE/UCASE... 常數)

安全性說明

項目說明
熵值估算~72 字符集,12 碼約 74 bits,符合 NIST 800-63B 建議(≥64 bits)。
預測困難度種子來自 CSPRNG,攻擊者無法從輸出反推內部狀態。
字符組平衡演算法保證每組至少出現一次,避免純數字/純字母弱密碼。
適用場景初始密碼、API Token、Email 驗證碼、Wi-Fi PSK 產生器。

結語

將此類別納入共用程式庫,即可在專案任何角落以 RandomPassword.Generate() 獲得高強度、符合合規要求的隨機字串。若需 FIPS 140-2 相容,請改用 RandomNumberGenerator (.NET Core 3.0+) 直接填充 Span<byte> 並自行映射字符集。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved