문제

우리 사이트의 사용자가 비밀번호를 잊어버리고 비밀번호 분실 페이지로 이동하는 경우 새 임시 비밀번호를 제공해야 합니다.이것이 얼마나 무작위인지는 별로 신경 쓰지 않습니다. 또는 "필요한" 강력한 암호 규칙과 모두 일치하는 경우 나중에 변경할 수 있는 암호를 제공하고 싶습니다.

응용 프로그램은 C#으로 작성된 웹 응용 프로그램입니다.그래서 나는 비열하고 Guid의 일부를 사용하는 쉬운 길을 갈 생각이었습니다.즉.

Guid.NewGuid().ToString("d").Substring(1,8)

제안?생각?

도움이 되었습니까?

다른 팁

public string CreatePassword(int length)
{
        const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        StringBuilder res = new StringBuilder();
        Random rnd = new Random();
        while (0 < length--)
        {
            res.Append(valid[rnd.Next(valid.Length)]);
        }
        return res.ToString();
}

이는 생성된 비밀번호에 사용 가능한 문자 목록에서 선택할 수 있다는 좋은 이점이 있습니다(예:숫자만, 대문자만 또는 소문자만 등)

내 코드의 주요 목표는 다음과 같습니다.

  1. 문자열의 분포는 거의 균일합니다(사소한 편차가 작다면 신경 쓰지 마세요).
  2. 각 인수 집합에 대해 수십억 개가 넘는 문자열을 출력합니다.PRNG가 20억(31비트 엔트로피)의 다른 값만 생성하는 경우 8자 문자열(~47비트 엔트로피)을 생성하는 것은 의미가 없습니다.
  3. 사람들이 이것을 비밀번호나 기타 보안 토큰으로 사용할 것으로 예상하기 때문에 안전합니다.

첫 번째 속성은 64비트 값 모듈로 알파벳 크기를 취하여 달성됩니다.작은 알파벳(예: 질문의 62자)의 경우 이는 무시할 수 있는 편향으로 이어집니다.두 번째와 세 번째 속성은 다음을 사용하여 달성됩니다. RNGCryptoServiceProvider 대신에 System.Random.

using System;
using System.Security.Cryptography;

public static string GetRandomAlphanumericString(int length)
{
    const string alphanumericCharacters =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
        "abcdefghijklmnopqrstuvwxyz" +
        "0123456789";
    return GetRandomString(length, alphanumericCharacters);
}

public static string GetRandomString(int length, IEnumerable<char> characterSet)
{
    if (length < 0)
        throw new ArgumentException("length must not be negative", "length");
    if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody
        throw new ArgumentException("length is too big", "length");
    if (characterSet == null)
        throw new ArgumentNullException("characterSet");
    var characterArray = characterSet.Distinct().ToArray();
    if (characterArray.Length == 0)
        throw new ArgumentException("characterSet must not be empty", "characterSet");

    var bytes = new byte[length * 8];
    new RNGCryptoServiceProvider().GetBytes(bytes);
    var result = new char[length];
    for (int i = 0; i < length; i++)
    {
        ulong value = BitConverter.ToUInt64(bytes, i * 8);
        result[i] = characterArray[value % (uint)characterArray.Length];
    }
    return new string(result);
}

(이것은 내 답변의 사본입니다. C#에서 임의의 8자 영숫자 문자열을 생성하려면 어떻게 해야 합니까?)

무작위 토큰을 생성하는 방법은 다음과 같습니다.

public string GenerateToken(int length)
{
    RNGCryptoServiceProvider cryptRNG = new RNGCryptoServiceProvider();
    byte[] tokenBuffer = new byte[length];
    cryptRNG.GetBytes(tokenBuffer);
    return Convert.ToBase64String(tokenBuffer);
}

이는 base-64 문자열을 반환하므로 출력 길이는 항상 4의 배수이며 추가 공간은 = 패딩 문자로.그만큼 length 매개변수는 출력 문자열이 아닌 바이트 버퍼의 길이를 지정합니다(따라서 아마도 해당 매개변수에 가장 적합한 이름은 아닐 것입니다. 이제 생각해 보겠습니다).이는 바이트 수를 제어합니다. 엔트로피 비밀번호가 있을 겁니다.그러나 base-64는 4자 블록을 사용하여 입력의 각 3바이트를 인코딩하기 때문에 3의 배수가 아닌 길이를 요청하면 추가 "공간"이 생겨서 다음을 사용하게 됩니다. = 여분을 채우기 위해.

어떤 이유로든 base-64 문자열을 사용하고 싶지 않다면 Convert.ToBase64String() 일반 문자열로 변환하거나 다음 중 하나를 사용하여 호출합니다. Encoding 행동 양식;예. Encoding.UTF8.GetString(tokenBuffer) - RNG에서 나오는 값의 전체 범위를 나타낼 수 있고 이것을 보내거나 저장하는 모든 위치와 호환되는 문자를 생성하는 문자 세트를 선택했는지 확인하십시오.예를 들어, 유니코드를 사용하면 많은 한자가 표시되는 경향이 있습니다.base-64를 사용하면 널리 호환되는 문자 집합이 보장되며, 적절한 해싱 알고리즘을 사용하는 한 이러한 문자열의 특성으로 인해 보안이 저하되어서는 안 됩니다.

이것은 훨씬 더 크지만 좀 더 포괄적인 것 같습니다.http://www.obviex.com/Samples/Password.aspx

///////////////////////////////////////////////////////////////////////////////
// SAMPLE: Generates random password, which complies with the strong password
//         rules and does not contain ambiguous characters.
//
// To run this sample, create a new Visual C# project using the Console
// Application template and replace the contents of the Class1.cs file with
// the code below.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// 
// Copyright (C) 2004 Obviex(TM). All rights reserved.
// 
using System;
using System.Security.Cryptography;

/// <summary>
/// This class can generate random passwords, which do not include ambiguous 
/// characters, such as I, l, and 1. The generated password will be made of
/// 7-bit ASCII symbols. Every four characters will include one lower case
/// character, one upper case character, one number, and one special symbol
/// (such as '%') in a random order. The password will always start with an
/// alpha-numeric character; it will not start with a special symbol (we do
/// this because some back-end systems do not like certain special
/// characters in the first position).
/// </summary>
public class RandomPassword
{
    // Define default min and max password lengths.
    private static int DEFAULT_MIN_PASSWORD_LENGTH  = 8;
    private static int DEFAULT_MAX_PASSWORD_LENGTH  = 10;

    // Define supported password characters divided into groups.
    // You can add (or remove) characters to (from) these groups.
    private static string PASSWORD_CHARS_LCASE  = "abcdefgijkmnopqrstwxyz";
    private static string PASSWORD_CHARS_UCASE  = "ABCDEFGHJKLMNPQRSTWXYZ";
    private static string PASSWORD_CHARS_NUMERIC= "23456789";
    private static string PASSWORD_CHARS_SPECIAL= "*$-+?_&=!%{}/";

    /// <summary>
    /// Generates a random password.
    /// </summary>
    /// <returns>
    /// Randomly generated password.
    /// </returns>
    /// <remarks>
    /// The length of the generated password will be determined at
    /// random. It will be no shorter than the minimum default and
    /// no longer than maximum default.
    /// </remarks>
    public static string Generate()
    {
        return Generate(DEFAULT_MIN_PASSWORD_LENGTH, 
                        DEFAULT_MAX_PASSWORD_LENGTH);
    }

    /// <summary>
    /// Generates a random password of the exact length.
    /// </summary>
    /// <param name="length">
    /// Exact password length.
    /// </param>
    /// <returns>
    /// Randomly generated password.
    /// </returns>
    public static string Generate(int length)
    {
        return Generate(length, length);
    }

    /// <summary>
    /// Generates a random password.
    /// </summary>
    /// <param name="minLength">
    /// Minimum password length.
    /// </param>
    /// <param name="maxLength">
    /// Maximum password length.
    /// </param>
    /// <returns>
    /// Randomly generated password.
    /// </returns>
    /// <remarks>
    /// The length of the generated password will be determined at
    /// random and it will fall with the range determined by the
    /// function parameters.
    /// </remarks>
    public static string Generate(int   minLength,
                                  int   maxLength)
    {
        // Make sure that input parameters are valid.
        if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
            return null;

        // Create a local array containing supported password characters
        // grouped by types. You can remove character groups from this
        // array, but doing so will weaken the password strength.
        char[][] charGroups = new char[][] 
        {
            PASSWORD_CHARS_LCASE.ToCharArray(),
            PASSWORD_CHARS_UCASE.ToCharArray(),
            PASSWORD_CHARS_NUMERIC.ToCharArray(),
            PASSWORD_CHARS_SPECIAL.ToCharArray()
        };

        // Use this array to track the number of unused characters in each
        // character group.
        int[] charsLeftInGroup = new int[charGroups.Length];

        // Initially, all characters in each group are not used.
        for (int i=0; i<charsLeftInGroup.Length; i++)
            charsLeftInGroup[i] = charGroups[i].Length;

        // Use this array to track (iterate through) unused character groups.
        int[] leftGroupsOrder = new int[charGroups.Length];

        // Initially, all character groups are not used.
        for (int i=0; i<leftGroupsOrder.Length; i++)
            leftGroupsOrder[i] = i;

        // Because we cannot use the default randomizer, which is based on the
        // current time (it will produce the same "random" number within a
        // second), we will use a random number generator to seed the
        // randomizer.

        // Use a 4-byte array to fill it with random bytes and convert it then
        // to an integer value.
        byte[] randomBytes = new byte[4];

        // Generate 4 random bytes.
        RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
        rng.GetBytes(randomBytes);

        // Convert 4 bytes into a 32-bit integer value.
        int seed = BitConverter.ToInt32(randomBytes, 0);

        // Now, this is real randomization.
        Random  random  = new Random(seed);

        // This array will hold password characters.
        char[] password = null;

        // Allocate appropriate memory for the password.
        if (minLength < maxLength)
            password = new char[random.Next(minLength, maxLength+1)];
        else
            password = new char[minLength];

        // Index of the next character to be added to password.
        int nextCharIdx;

        // Index of the next character group to be processed.
        int nextGroupIdx;

        // Index which will be used to track not processed character groups.
        int nextLeftGroupsOrderIdx;

        // Index of the last non-processed character in a group.
        int lastCharIdx;

        // Index of the last non-processed group.
        int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;

        // Generate password characters one at a time.
        for (int i=0; i<password.Length; i++)
        {
            // If only one character group remained unprocessed, process it;
            // otherwise, pick a random character group from the unprocessed
            // group list. To allow a special character to appear in the
            // first position, increment the second parameter of the Next
            // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
            if (lastLeftGroupsOrderIdx == 0)
                nextLeftGroupsOrderIdx = 0;
            else
                nextLeftGroupsOrderIdx = random.Next(0, 
                                                     lastLeftGroupsOrderIdx);

            // Get the actual index of the character group, from which we will
            // pick the next character.
            nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];

            // Get the index of the last unprocessed characters in this group.
            lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;

            // If only one unprocessed character is left, pick it; otherwise,
            // get a random character from the unused character list.
            if (lastCharIdx == 0)
                nextCharIdx = 0;
            else
                nextCharIdx = random.Next(0, lastCharIdx+1);

            // Add this character to the password.
            password[i] = charGroups[nextGroupIdx][nextCharIdx];

            // If we processed the last character in this group, start over.
            if (lastCharIdx == 0)
                charsLeftInGroup[nextGroupIdx] = 
                                          charGroups[nextGroupIdx].Length;
            // There are more unprocessed characters left.
            else
            {
                // Swap processed character with the last unprocessed character
                // so that we don't pick it until we process all characters in
                // this group.
                if (lastCharIdx != nextCharIdx)
                {
                    char temp = charGroups[nextGroupIdx][lastCharIdx];
                    charGroups[nextGroupIdx][lastCharIdx] = 
                                charGroups[nextGroupIdx][nextCharIdx];
                    charGroups[nextGroupIdx][nextCharIdx] = temp;
                }
                // Decrement the number of unprocessed characters in
                // this group.
                charsLeftInGroup[nextGroupIdx]--;
            }

            // If we processed the last group, start all over.
            if (lastLeftGroupsOrderIdx == 0)
                lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
            // There are more unprocessed groups left.
            else
            {
                // Swap processed group with the last unprocessed group
                // so that we don't pick it until we process all groups.
                if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
                {
                    int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
                    leftGroupsOrder[lastLeftGroupsOrderIdx] = 
                                leftGroupsOrder[nextLeftGroupsOrderIdx];
                    leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
                }
                // Decrement the number of unprocessed groups.
                lastLeftGroupsOrderIdx--;
            }
        }

        // Convert password characters into a string and return the result.
        return new string(password);
     }
}

/// <summary>
/// Illustrates the use of the RandomPassword class.
/// </summary>
public class RandomPasswordTest
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // Print 100 randomly generated passwords (8-to-10 char long).
        for (int i=0; i<100; i++)
            Console.WriteLine(RandomPassword.Generate(8, 10));
    }
}
//
// END OF FILE
///////////////////////////////////////////////////////////////////////////////

나는 이것이 오래된 스레드라는 것을 알고 있지만 누군가가 사용할 수 있는 매우 간단한 솔루션을 가지고 있습니다.구현하기 쉽고, 이해하기 쉽고, 검증하기 쉽습니다.

다음 요구 사항을 고려하십시오.

최소 2개의 소문자, 2개의 대문자, 2개의 숫자가 포함된 임의의 비밀번호를 생성해야 합니다.비밀번호 길이도 최소 8자 이상이어야 합니다.

다음 정규식은 이 사례를 검증할 수 있습니다.

^(?=\b\w*[a-z].*[a-z]\w*\b)(?=\b\w*[A-Z].*[A-Z]\w*\b)(?=\b\w*[0-9].*[0-9]\w*\b)[a-zA-Z0-9]{8,}$

이 질문의 범위를 벗어납니다. 하지만 정규식은 다음을 기반으로 합니다. 미리보기/뒤돌아보기 그리고 둘러보기.

다음 코드는 이 요구 사항에 맞는 임의의 문자 집합을 생성합니다.

public static string GeneratePassword(int lowercase, int uppercase, int numerics) {
    string lowers = "abcdefghijklmnopqrstuvwxyz";
    string uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    string number = "0123456789";

    Random random = new Random();

    string generated = "!";
    for (int i = 1; i <= lowercase; i++)
        generated = generated.Insert(
            random.Next(generated.Length), 
            lowers[random.Next(lowers.Length - 1)].ToString()
        );

    for (int i = 1; i <= uppercase; i++)
        generated = generated.Insert(
            random.Next(generated.Length), 
            uppers[random.Next(uppers.Length - 1)].ToString()
        );

    for (int i = 1; i <= numerics; i++)
        generated = generated.Insert(
            random.Next(generated.Length), 
            number[random.Next(number.Length - 1)].ToString()
        );

    return generated.Replace("!", string.Empty);

}

위의 요구 사항을 충족하려면 다음을 호출하면 됩니다.

String randomPassword = GeneratePassword(3, 3, 3);

코드가 잘못된 문자("!") - 문자열에 새 문자를 삽입할 수 있는 길이가 있어야 합니다.

그런 다음 1부터 필요한 소문자 수까지 반복하고, 반복할 때마다 소문자 목록에서 임의의 항목을 가져와 문자열의 임의 위치에 삽입합니다.

그런 다음 대문자와 숫자에 대해 루프를 반복합니다.

이것은 길이 =의 문자열을 다시 제공합니다. lowercase + uppercase + numerics 원하는 개수의 소문자, 대문자, 숫자가 무작위 순서로 배치되어 있습니다.

이런 종류의 비밀번호에 대해 나는 더 쉽게 "사용되는" 비밀번호를 생성할 수 있는 시스템을 사용하는 경향이 있습니다.짧고 발음 가능한 부분과 몇 개의 숫자로 구성되는 경우가 많으며 문자 간 모호함이 없습니다(0 또는 O입니까?1 또는 I?).다음과 같은 것

string[] words = { 'bur', 'ler', 'meh', 'ree' };
string word = "";

Random rnd = new Random();
for (i = 0; i < 3; i++)
   word += words[rnd.Next(words.length)]

int numbCount = rnd.Next(4);
for (i = 0; i < numbCount; i++)
  word += (2 + rnd.Next(7)).ToString();

return word;

(브라우저에 바로 입력되므로 지침으로만 사용하십시오.또한 더 많은 단어를 추가하십시오).

내가 만들었다 이 수업 RNGCryptoServiceProvider를 사용하며 유연합니다.예:

var generator = new PasswordGenerator(minimumLengthPassword: 8,
                                      maximumLengthPassword: 15,
                                      minimumUpperCaseChars: 2,
                                      minimumNumericChars: 3,
                                      minimumSpecialChars: 2);
string password = generator.Generate();

저는 Membership.GeneratePassword()가 생성하는 비밀번호가 너무 보기 흉하고 특수 문자가 너무 많기 때문에 마음에 들지 않습니다.

이 코드는 그다지 어렵지 않은 10자리 비밀번호를 생성합니다.

string password = Guid.NewGuid().ToString("N").ToLower()
                      .Replace("1", "").Replace("o", "").Replace("0","")
                      .Substring(0,10);

물론, Regex를 사용하여 모든 교체를 수행할 수 있지만 이것이 더 읽기 쉽고 유지 관리하기 쉬운 IMO입니다.

저는 KeePass에 내장된 비밀번호 생성기에 항상 매우 만족해 왔습니다.KeePass는 .Net 프로그램이자 오픈 소스이기 때문에 코드를 조금 살펴보기로 결정했습니다.결국 표준 응용 프로그램 설치에 제공된 복사본인 KeePass.exe를 내 프로젝트의 참조로 참조하고 아래 코드를 작성하게 되었습니다.KeePass 덕분에 얼마나 유연한지 확인할 수 있습니다.길이, 포함할 문자/포함하지 않을 문자 등을 지정할 수 있습니다.

using KeePassLib.Cryptography.PasswordGenerator;
using KeePassLib.Security;


public static string GeneratePassword(int passwordLength, bool lowerCase, bool upperCase, bool digits,
        bool punctuation, bool brackets, bool specialAscii, bool excludeLookAlike)
    {
        var ps = new ProtectedString();
        var profile = new PwProfile();
        profile.CharSet = new PwCharSet();
        profile.CharSet.Clear();

        if (lowerCase)
            profile.CharSet.AddCharSet('l');
        if(upperCase)
            profile.CharSet.AddCharSet('u');
        if(digits)
            profile.CharSet.AddCharSet('d');
        if (punctuation)
            profile.CharSet.AddCharSet('p');
        if (brackets)
            profile.CharSet.AddCharSet('b');
        if (specialAscii)
            profile.CharSet.AddCharSet('s');

        profile.ExcludeLookAlike = excludeLookAlike;
        profile.Length = (uint)passwordLength;
        profile.NoRepeatingCharacters = true;

        KeePassLib.Cryptography.PasswordGenerator.PwGenerator.Generate(out ps, profile, null, _pool);

        return ps.ReadString();
    }

저는 멤버십 공급자에서 사용할 수 있는 것과 유사한 이 방법을 만들었습니다.일부 응용 프로그램에 웹 참조를 추가하지 않으려는 경우 유용합니다.

잘 작동합니다.

public static string GeneratePassword(int Length, int NonAlphaNumericChars)
    {
        string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
        string allowedNonAlphaNum = "!@#$%^&*()_-+=[{]};:<>|./?";
        Random rd = new Random();

        if (NonAlphaNumericChars > Length || Length <= 0 || NonAlphaNumericChars < 0)
            throw new ArgumentOutOfRangeException();

            char[] pass = new char[Length];
            int[] pos = new int[Length];
            int i = 0, j = 0, temp = 0;
            bool flag = false;

            //Random the position values of the pos array for the string Pass
            while (i < Length - 1)
            {
                j = 0;
                flag = false;
                temp = rd.Next(0, Length);
                for (j = 0; j < Length; j++)
                    if (temp == pos[j])
                    {
                        flag = true;
                        j = Length;
                    }

                if (!flag)
                {
                    pos[i] = temp;
                    i++;
                }
            }

            //Random the AlphaNumericChars
            for (i = 0; i < Length - NonAlphaNumericChars; i++)
                pass[i] = allowedChars[rd.Next(0, allowedChars.Length)];

            //Random the NonAlphaNumericChars
            for (i = Length - NonAlphaNumericChars; i < Length; i++)
                pass[i] = allowedNonAlphaNum[rd.Next(0, allowedNonAlphaNum.Length)];

            //Set the sorted array values by the pos array for the rigth posistion
            char[] sorted = new char[Length];
            for (i = 0; i < Length; i++)
                sorted[i] = pass[pos[i]];

            string Pass = new String(sorted);

            return Pass;
    }

나는 소프트웨어 키 생성과 마찬가지로 암호 생성을 살펴보는 것을 좋아합니다.모범 사례를 따르는 일련의 문자 중에서 선택해야 합니다.무엇을 가져 가라 @Radu094 답변됨 모범 사례를 따르도록 수정하고 수정하세요.문자 배열에 모든 문자를 넣지 마십시오.일부 편지는 전화로 말하거나 이해하기가 더 어렵습니다.

또한 생성된 비밀번호에 체크섬을 사용하여 해당 비밀번호가 본인이 생성했는지 확인하는 것도 고려해야 합니다.이를 달성하는 좋은 방법은 다음을 사용하는 것입니다. LUHN 알고리즘.

여기에 내가 빨리 정리한 것이 있습니다.

    public string GeneratePassword(int len)
    {
        string res = "";
        Random rnd = new Random();
        while (res.Length < len) res += (new Func<Random, string>((r) => {
            char c = (char)((r.Next(123) * DateTime.Now.Millisecond % 123)); 
            return (Char.IsLetterOrDigit(c)) ? c.ToString() : ""; 
        }))(rnd);
        return res;
    }
public static string GeneratePassword(int passLength) {
        var chars = "abcdefghijklmnopqrstuvwxyz@#$&ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var random = new Random();
        var result = new string(
            Enumerable.Repeat(chars, passLength)
                      .Select(s => s[random.Next(s.Length)])
                      .ToArray());
        return result;
    }

이것은 짧고 나에게 아주 효과적입니다.

public static string GenerateRandomCode(int length)
{
    Random rdm = new Random();
    StringBuilder sb = new StringBuilder();

    for(int i = 0; i < length; i++)
        sb.Append(Convert.ToChar(rdm.Next(101,132)));

    return sb.ToString();
}

내 웹사이트에서는 다음 방법을 사용합니다.

    //Symb array
    private const string _SymbolsAll = "~`!@#$%^&*()_+=-\\|[{]}'\";:/?.>,<";

    //Random symb
    public string GetSymbol(int Length)
    {
        Random Rand = new Random(DateTime.Now.Millisecond);
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < Length; i++)
            result.Append(_SymbolsAll[Rand.Next(0, _SymbolsAll.Length)]);
        return result.ToString();
    }

문자열 편집 _SymbolsAll 배열 목록의 경우.

허용되는 답변에 몇 가지 추가 코드를 추가했습니다.Random을 사용하여 답변을 개선하고 일부 비밀번호 옵션을 허용합니다.또한 KeePass 답변의 일부 옵션이 마음에 들었지만 내 솔루션에 실행 파일을 포함하고 싶지 않았습니다.

private string RandomPassword(int length, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
    if (length < 8 || length > 128) throw new ArgumentOutOfRangeException("length");
    if (!includeCharacters && !includeNumbers && !includeNonAlphaNumericCharacters) throw new ArgumentException("RandomPassword-Key arguments all false, no values would be returned");

    string pw = "";
    do
    {
        pw += System.Web.Security.Membership.GeneratePassword(128, 25);
        pw = RemoveCharacters(pw, includeCharacters, includeNumbers, includeUppercase, includeNonAlphaNumericCharacters, includeLookAlikes);
    } while (pw.Length < length);

    return pw.Substring(0, length);
}

private string RemoveCharacters(string passwordString, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
    if (!includeCharacters)
    {
        var remove = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
        foreach (string r in remove)
        {
            passwordString = passwordString.Replace(r, string.Empty);
            passwordString = passwordString.Replace(r.ToUpper(), string.Empty);
        }
    }

    if (!includeNumbers)
    {
        var remove = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
        foreach (string r in remove)
            passwordString = passwordString.Replace(r, string.Empty);
    }

    if (!includeUppercase)
        passwordString = passwordString.ToLower();

    if (!includeNonAlphaNumericCharacters)
    {
        var remove = new string[] { "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "=", "{", "}", "[", "]", "|", "\\", ":", ";", "<", ">", "/", "?", "." };
        foreach (string r in remove)
            passwordString = passwordString.Replace(r, string.Empty);
    }

    if (!includeLookAlikes)
    {
        var remove = new string[] { "(", ")", "0", "O", "o", "1", "i", "I", "l", "|", "!", ":", ";" };
        foreach (string r in remove)
            passwordString = passwordString.Replace(r, string.Empty);
    }

    return passwordString;
}

이것은 무작위 비밀번호 생성을 검색했을 때 첫 번째 링크였으며 다음은 현재 질문의 범위를 벗어나지만 고려해야 할 중요할 수 있습니다.

  • 다음과 같은 가정을 바탕으로 System.Web.Security.Membership.GeneratePassword 최소 20%의 문자가 영숫자가 아닌 문자로 암호화되어 안전합니다.
  • 이 경우 문자를 제거하고 문자열을 추가하는 것이 좋은 방법으로 간주되고 충분한 엔트로피를 제공하는지 확실하지 않습니다.
  • 어떤 방식으로든 구현을 고려하고 싶을 수도 있습니다. SecureString 메모리에 안전한 비밀번호 저장을 위해.

validChars는 어떤 구성이든 가능하지만 제어 문자를 제거하는 ASCII 코드 범위를 기반으로 선택하기로 결정했습니다.이 예에서는 12자 문자열입니다.

string validChars = String.Join("", Enumerable.Range(33, (126 - 33)).Where(i => !(new int[] { 34, 38, 39, 44, 60, 62, 96 }).Contains(i)).Select(i => { return (char)i; }));
string.Join("", Enumerable.Range(1, 12).Select(i => { return validChars[(new Random(Guid.NewGuid().GetHashCode())).Next(0, validChars.Length - 1)]; }))
 Generate random password of specified length with 
  - Special characters   
  - Number
  - Lowecase
  - Uppercase

  public static string CreatePassword(int length = 12)
    {
        const string lower = "abcdefghijklmnopqrstuvwxyz";
        const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        const string number = "1234567890";
        const string special = "!@#$%^&*";

        var middle = length / 2;
        StringBuilder res = new StringBuilder();
        Random rnd = new Random();
        while (0 < length--)
        {
            if (middle == length)
            {
                res.Append(number[rnd.Next(number.Length)]);
            }
            else if (middle - 1 == length)
            {
                res.Append(special[rnd.Next(special.Length)]);
            }
            else
            {
                if (length % 2 == 0)
                {
                    res.Append(lower[rnd.Next(lower.Length)]);
                }
                else
                {
                    res.Append(upper[rnd.Next(upper.Length)]);
                }
            }
        }
        return res.ToString();
    }

냄비에 또 다른 잘못된 답변을 추가하겠습니다.

기계 간 통신을 위해 임의의 비밀번호가 필요한 사용 사례가 있으므로 사람의 가독성에 대한 요구 사항이 없습니다.나도 접근할 수 없어 Membership.GeneratePassword 내 프로젝트에 종속성을 추가하고 싶지 않습니다.

나는 꽤 확신한다 Membership.GeneratePassword 에서는 이와 유사한 작업을 수행하고 있지만 여기에서 그릴 캐릭터 풀을 조정할 수 있습니다.

public static class PasswordGenerator
{
    private readonly static Random _rand = new Random();

    public static string Generate(int length = 24)
    {
        const string lower = "abcdefghijklmnopqrstuvwxyz";
        const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        const string number = "1234567890";
        const string special = "!@#$%^&*_-=+";

        // Get cryptographically random sequence of bytes
        var bytes = new byte[length];
        new RNGCryptoServiceProvider().GetBytes(bytes);

        // Build up a string using random bytes and character classes
        var res = new StringBuilder();
        foreach(byte b in bytes)
        {
            // Randomly select a character class for each byte
            switch (_rand.Next(4))
            {
                // In each case use mod to project byte b to the correct range
                case 0:
                    res.Append(lower[b % lower.Count()]);
                    break;
                case 1:
                    res.Append(upper[b % upper.Count()]);
                    break;
                case 2:
                    res.Append(number[b % number.Count()]);
                    break;
                case 3:
                    res.Append(special[b % special.Count()]);
                    break;
            }
        }
        return res.ToString();
    }
}

그리고 몇 가지 예제 출력은 다음과 같습니다.

PasswordGenerator.Generate(12)
"pzY=64@-ChS$"
"BG0OsyLbYnI_"
"l9#5^2&adj_i"
"#++Ws9d$%O%X"
"IWhdIN-#&O^s"

이용에 관한 불만을 사전에 방지하기 위해 Random:무작위성의 주요 소스는 여전히 암호화 RNG입니다.비록 당신이 나오는 시퀀스를 결정론적으로 미리 정할 수 있다고 하더라도 Random (만 생산했다고 말하자 1) 당신은 여전히 ​​선택될 다음 문자를 알지 못할 것입니다. ~일 것이다 가능성의 범위를 제한합니다).

간단한 확장 중 하나는 다양한 문자 집합에 가중치를 추가하는 것입니다. 이는 최대 값을 높이고 가중치를 높이기 위해 fall-through 사례를 추가하는 것처럼 간단할 수 있습니다.

switch (_rand.Next(6))
{
    // Prefer letters 2:1
    case 0:
    case 1:
        res.Append(lower[b % lower.Count()]);
        break;
    case 2:
    case 3:
        res.Append(upper[b % upper.Count()]);
        break;
    case 4:
        res.Append(number[b % number.Count()]);
        break;
    case 5:
        res.Append(special[b % special.Count()]);
        break;
}

보다 인간적인 무작위 비밀번호 생성기를 위해 저는 다음을 사용하여 프롬프트 시스템을 구현한 적이 있습니다. EFF 주사위 단어 목록.

타이머 삽입:타이머1, 버튼 2개:버튼1, 버튼2, 텍스트 상자 1개:textBox1 및 콤보 상자:콤보박스1.다음 사항을 선언했는지 확인하세요.

int count = 0;

소스 코드:

 private void button1_Click(object sender, EventArgs e)
    {
    // This clears the textBox, resets the count, and starts the timer
        count = 0;
        textBox1.Clear();
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
    // This generates the password, and types it in the textBox
        count += 1;
            string possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
            string psw = "";
            Random rnd = new Random { };
            psw += possible[rnd.Next(possible.Length)];
            textBox1.Text += psw;
            if (count == (comboBox1.SelectedIndex + 1))
            {
                timer1.Stop();
            }
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        // This adds password lengths to the comboBox to choose from.
        comboBox1.Items.Add("1");
        comboBox1.Items.Add("2");
        comboBox1.Items.Add("3");
        comboBox1.Items.Add("4");
        comboBox1.Items.Add("5");
        comboBox1.Items.Add("6");
        comboBox1.Items.Add("7");
        comboBox1.Items.Add("8");
        comboBox1.Items.Add("9");
        comboBox1.Items.Add("10");
        comboBox1.Items.Add("11");
        comboBox1.Items.Add("12");
    }
    private void button2_click(object sender, EventArgs e)
    {
        // This encrypts the password
        tochar = textBox1.Text;
        textBox1.Clear();
        char[] carray = tochar.ToCharArray();
        for (int i = 0; i < carray.Length; i++)
        {
            int num = Convert.ToInt32(carray[i]) + 10;
            string cvrt = Convert.ToChar(num).ToString();
            textBox1.Text += cvrt;
        }
    }
public string Sifre_Uret(int boy, int noalfa)
{

    //  01.03.2016   
    // Genel amaçlı şifre üretme fonksiyonu


    //Fonskiyon 128 den büyük olmasına izin vermiyor.
    if (boy > 128 ) { boy = 128; }
    if (noalfa > 128) { noalfa = 128; }
    if (noalfa > boy) { noalfa = boy; }


    string passch = System.Web.Security.Membership.GeneratePassword(boy, noalfa);

    //URL encoding ve Url Pass + json sorunu yaratabilecekler pass ediliyor.
    //Microsoft Garanti etmiyor. Alfa Sayısallar Olabiliyorimiş . !@#$%^&*()_-+=[{]};:<>|./?.
    //https://msdn.microsoft.com/tr-tr/library/system.web.security.membership.generatepassword(v=vs.110).aspx


    //URL ve Json ajax lar için filtreleme
    passch = passch.Replace(":", "z");
    passch = passch.Replace(";", "W");
    passch = passch.Replace("'", "t");
    passch = passch.Replace("\"", "r");
    passch = passch.Replace("/", "+");
    passch = passch.Replace("\\", "e");

    passch = passch.Replace("?", "9");
    passch = passch.Replace("&", "8");
    passch = passch.Replace("#", "D");
    passch = passch.Replace("%", "u");
    passch = passch.Replace("=", "4");
    passch = passch.Replace("~", "1");

    passch = passch.Replace("[", "2");
    passch = passch.Replace("]", "3");
    passch = passch.Replace("{", "g");
    passch = passch.Replace("}", "J");


    //passch = passch.Replace("(", "6");
    //passch = passch.Replace(")", "0");
    //passch = passch.Replace("|", "p");
    //passch = passch.Replace("@", "4");
    //passch = passch.Replace("!", "u");
    //passch = passch.Replace("$", "Z");
    //passch = passch.Replace("*", "5");
    //passch = passch.Replace("_", "a");

    passch = passch.Replace(",", "V");
    passch = passch.Replace(".", "N");
    passch = passch.Replace("+", "w");
    passch = passch.Replace("-", "7");





    return passch;



}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top