Skip to content

יצירת סיסמאות אקראיות ב־.NET ללא הטיית מודולו

יצירת סיסמאות אקראיות ב־.NET ללא הטיית מודולו

הקוד להמחשה ולא הורץ.

המקור האנגלי פורסם בתאריך 2022-03-03T09:09:00.007+02:00. המאמר המקורי באנגלית

הדוגמה הארכיונית מפנה למחולל סיסמאות ב־Stack Overflow. עצם השימוש במקור בתים קריפטוגרפי אינו הופך את כל השלבים למתאימים לסיסמאות: הפעולה byte % 87 יוצרת הטיה בבחירת התווים, והשימוש המאוחר ב־System.Random אינו תחליף קריפטוגרפי. הדוגמה המתוקנת להלן משתמשת ב־RandomNumberGenerator.GetInt32 בכל בחירה. [1]

לבית יש 256 ערכים אפשריים. חלוקתם ל־87 קבוצות משאירה שארית, ולכן קבוצות מסוימות מקבלות יותר ערכי קלט. GetInt32 משתמש בדגימת דחייה במקום בצמצום מודולו פשוט. מחרוזת סימני הפיסוק המקורית מכילה 25 תווים, המתאימים לאינדקסים 62 עד 86; גודל המערך אינו הבעיה. [1]

מדיניות תווים מפורשת

הפונקציה להמחשה מיועדת ל־.NET מודרני ומייצרת בדיוק symbolCount סימני פיסוק, ולא את המספר המזערי שבדוגמה המקורית. היא ממלאת את שאר המקומות באותיות ובספרות, ואז מערבבת באמצעות אלגוריתם Fisher–Yates עם אקראיות קריפטוגרפית. בכל קבוצת תווים אין כפילויות. טווח האורך 16–128 הוא מדיניות לדוגמה, ולא הבטחה אוניברסלית לחוזק סיסמה. אין כאן הבטחה שתופיע לפחות ספרה אחת או אותיות משני הגדלים. [1]

using System;
using System.Security.Cryptography;

public static class PasswordExample
{
    // Illustrative only; not executed as part of this article.
    public static string Generate(int length = 20, int symbolCount = 4)
    {
        const string LettersAndDigits =
            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        const string Symbols = "!@#$%^&*()_-+=[{]};:>|./?";
        if (length < 16 || length > 128)
            throw new ArgumentOutOfRangeException(nameof(length));
        if (symbolCount < 0 || symbolCount > length)
            throw new ArgumentOutOfRangeException(nameof(symbolCount));

        char[] result = new char[length];
        for (int i = 0; i < length; i++)
        {
            string alphabet = i < symbolCount ? Symbols : LettersAndDigits;
            result[i] = alphabet[RandomNumberGenerator.GetInt32(alphabet.Length)];
        }
        for (int i = result.Length - 1; i > 0; i--)
        {
            int j = RandomNumberGenerator.GetInt32(i + 1);
            (result[i], result[j]) = (result[j], result[i]);
        }
        string password = new string(result);
        Array.Clear(result, 0, result.Length);
        return password; // The returned immutable string cannot be wiped reliably.
    }
}

יש לבחור אורך וקבוצת תווים שהמערכת המקבלת תומכת בהם בפועל. אין לרשום את התוצאה ביומן ואין לעשות בה שימוש חוזר. ניקוי מערך התווים הזמני אינו מוחק את המחרוזת המוחזרת או את כל ההעתקים בזמן הריצה. זו דוגמת קוד שלא הורצה; לא נוצרה סיסמה ולא שונה חשבון. בגרסאות יעד ישנות יש להשתמש בפונקציית עזר קריפטוגרפית שנבדקה ומבצעת דגימת דחייה, ולא להחליף אותה ב־System.Random.

מקורות ראשוניים

  1. Microsoft RandomNumberGenerator.GetInt32

הקישורים המקוריים נשמרו לצורכי ייחוס. הם אינם אישור לתקינות הקוד הישן; זמינותם הנוכחית לא אומתה.

Post a Comment

Previous Post Next Post