【问题标题】:Make a password generator制作密码生成器
【发布时间】:2019-05-10 16:29:16
【问题描述】:

我目前正在尝试制作一个随机密码生成器。
如果我只选择一种符号,我的代码就可以正常工作。

让我的代码可以用于多种类型的最佳方法是什么?
另外,您会添加哪些参数以使密码更安全?
我正在考虑添加一个 if 循环来检查一行中是否有两个以上相同的字母、符号或数字。

这就是我的界面的样子:

这是我的代码:

public partial class Form1 : Form
{
    // Max number of identical characters in a row 
    const int Maximum_Identical = 2;
    // lower case chars
    const string lower_chars = "abcdefghijklmnopqrstuvwxyz";
    // capital chars
    const string capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    // numbers
    const string numbers = "0123456789";
    // symbols
    const string symbols = @"!#$%&*@\";
    // password lenght 
    int lenght;

    private void button1_Click(object sender, EventArgs e)
    {
        //use stringbuilder so I can add more chars later
        StringBuilder password = new StringBuilder();
        //take max lenght from numericUpDown
        lenght = Convert.ToInt32(numericUpDown1.Value);
        // random instance so I can use Next and don't get loops
        Random rdm = new Random();

        if (small_letters__Box.Checked)
        {
            //add a random small character to pass untill it reaches the selected lenght  
            while (lenght-- > 0 )
            {
                password.Append(lower_chars[rdm.Next(lower_chars.Length)]);
            }
        }

        if (capital_letters__Box.Checked)
        {
            //add a random capital character to pass untill it reaches the selected lenght  
            while (lenght-- > 0)
            {
                password.Append(capital_chars[rdm.Next(capital_chars.Length)]);
            }
        }

        if (numbers_Box.Checked)
        {
            //add a random character to pass untill it reaches the selected lenght  
            while (lenght-- > 0)
            {
                password.Append(numbers[rdm.Next(numbers.Length)]);
            }
        }

        if (symbols_Box.Checked)
        {
            //add a random character to pass untill it reaches the selected lenght  
            while (lenght-- > 0)
            {
                password.Append(symbols[rdm.Next(symbols.Length)]);
            }
        }
        textBox1.Text = password.ToString();
    }

    private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {

    }
}

【问题讨论】:

  • 我不允许密码长度为 1 的选项;)

标签: c# passwords


【解决方案1】:

您的密码生成有 2 个步骤。

  1. 确定字符集
  2. 从长度为n的字符集中随机创建密码

函数1创建字符集:

// Make sure you have using System.Linq;
private List<char> GetCharacterSet()
{
    IEnumerable<char> returnSet = new char[]{};

    if (small_letters__Box.Checked)
    {
        returnSet = returnSet.Append(lower_chars);
    }

    if (capital_letters__Box.Checked)
    {
        returnSet = returnSet.Append(capital_chars);
    }

    if (numbers_Box.Checked)
    {
        returnSet = returnSet.Append(numbers);
    }

    if (symbols_Box.Checked)
    {
        returnSet = returnSet.Append(symbols);
    }

    return returnSet.ToList();
}

函数 2 根据您的字符集创建一个给定长度的密码

private string GetPassword(int length, List<char> characterSet)
{
    if(characterSet.Count < 1)
    {
        throw new ArgumentException("characterSet contains no items!");
    }

    if(length < 1)
    {
        return "";
    }

    Random rdm = new Random();

    StringBuilder password = new StringBuilder();

    for(int i = 0; i < length; i++){
        int charIndex = rdm.Next(0, characterSet.Count)
        password.Append(characterSet[charIndex]);
    }

    return password.ToString();
}

然后只需安装您的按钮单击事件处理程序即可调用这些函数并显示生成的密码。

【讨论】:

  • 此代码存在问题,如果您选择所有框,则可能会出现例如您获得的密码不包含大写字母或不包含符号的密码。为了解决这个问题,您必须从每个选定的字符集中选择随机字符,以确保如果选中一个框,您会得到这些字符。
  • 没错,我想这取决于 OP 想要定义的规则。可能有一些字符集您不想对其施加此限制。 OP 添加了另一个复选框,用于在密码中包含字符 =。选中此框不一定总是包含=
【解决方案2】:

下面的代码是我几年前写的已经写好的代码,我仍然在我的许多项目中使用它,它涵盖了你需要的所有内容

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading;

public static class ArrayExtentions
{
    public static object[] Shuffle(this object[] array)
    {
        var alreadySwaped = new HashSet<Tuple<int, int>>();
        var rndLoopCount = RandomUtils.GetRandom(Convert.ToInt32(array.Length / 4), Convert.ToInt32((array.Length / 2) + 1));

        for (var i = 0; i <= rndLoopCount; i++)
        {
            int rndIndex1 = 0, rndIndex2 = 0;
            do
            {
                rndIndex1 = RandomUtils.GetRandom(0, array.Length);
                rndIndex2 = RandomUtils.GetRandom(0, array.Length);
            } while (alreadySwaped.Contains(new Tuple<int, int>(rndIndex1, rndIndex2)));

            alreadySwaped.Add(new Tuple<int, int>(rndIndex1, rndIndex2));
            var swappingItem = array[rndIndex1];
            array[rndIndex1] = array[rndIndex2];
            array[rndIndex2] = swappingItem;
        }
        return array;
    }

}

public class RandomUtils
{
    private static readonly ThreadLocal<Random> RndLocal = new ThreadLocal<Random>(() => new Random(GetUniqueSeed()));

    private static int GetUniqueSeed()
    {
        long next, current;
        var guid = Guid.NewGuid().ToByteArray();
        var seed = BitConverter.ToInt64(guid, 0);

        do
        {
            current = Interlocked.Read(ref seed);
            next = current * BitConverter.ToInt64(guid, 3);
        } while (Interlocked.CompareExchange(ref seed, next, current) != current);

        return (int)next ^ Environment.TickCount;
    }

    public static int GetRandom(int min, int max)
    {
        Contract.Assert(max >= min);
        return RndLocal.Value.Next(min, max);
    }

    public static int GetRandom(int max)
    {
        return RndLocal.Value.Next(max);
    }

    public static double GetRandom()
    {
        return RndLocal.Value.NextDouble();
    }
}

public class StringUtility
{
    private const string UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUWXYZ";
    private const string LowerAlpha = "abcdefghijklmnopqrstuwxyz";
    private const string Numbers = "0123456789";
    private const string SpecialChars = "~!@#$%^&*()_-+=.?";


    private static string CreateSourceString(bool includeLowerCase, bool includeUpperCase, bool includenumbers, bool includeSpChars)
    {
        Contract.Assert(includeLowerCase || includeUpperCase || includenumbers || includeSpChars);
        var sb = new StringBuilder();

        if (includeLowerCase) sb.Append(LowerAlpha);
        if (includeUpperCase) sb.Append(UpperAlpha);
        if (includenumbers) sb.Append(Numbers);
        if (includeSpChars) sb.Append(SpecialChars);
        return sb.ToString();
    }

    private static string GenerateString(string sourceString, int length = 6)
    {
        var rndString = Shuffle(sourceString);
        var builder = new StringBuilder();
        for (var i = 0; i < length; i++)
            builder.Append(rndString[RandomUtils.GetRandom(0, rndString.Length)]);
        return builder.ToString();
    }
    public static string GenerateRandomString(int length = 6,
        bool includenumbers = false,
        bool includeSpChars = false)
    {
        var sourceStr = CreateSourceString(true, true, includenumbers, includeSpChars);
        return GenerateString(sourceStr, length);
    }


    public static string GenerateRandomString(int minLength,
        int maxLength,
        bool includenumbers = false,
        bool includeSpChars = false)
    {
        if (maxLength < minLength) maxLength = minLength;
        var len = RandomUtils.GetRandom(minLength, maxLength + 1);
        return GenerateRandomString(len, includenumbers, includeSpChars);
    }

    public static string Shuffle(string str)
    {
        var alreadySwaped = new HashSet<Tuple<int, int>>();
        var rndLoopCount = RandomUtils.GetRandom(Convert.ToInt32(str.Length / 4), Convert.ToInt32((str.Length / 2) + 1));
        var strArray = str.ToArray();
        for (var i = 0; i <= rndLoopCount; i++)
        {
            int rndIndex1 = 0, rndIndex2 = 0;
            do
            {
                rndIndex1 = RandomUtils.GetRandom(0, str.Length);
                rndIndex2 = RandomUtils.GetRandom(0, str.Length);
            } while (alreadySwaped.Contains(new Tuple<int, int>(rndIndex1, rndIndex2)));

            alreadySwaped.Add(new Tuple<int, int>(rndIndex1, rndIndex2));
            var swappingChar = strArray[rndIndex1];
            strArray[rndIndex1] = strArray[rndIndex2];
            strArray[rndIndex2] = swappingChar;
        }
        return new string(strArray);
    }

    public static string GeneratePassword(PasswordComplexity complexityLevel)
    {
        switch (complexityLevel)
        {
            case PasswordComplexity.Simple: return GenerateSimplePassword();
            case PasswordComplexity.Medium: return GenerateMediumPassword();
            case PasswordComplexity.Strong: return GenerateStrongPassword();
            case PasswordComplexity.Stronger: return GenerateStrongerPassword();
        }
        return null;
    }

    private static string GenerateSimplePassword()
    {
        return GenerateRandomString(6, 9);
    }

    private static string GenerateMediumPassword()
    {
        var passLen = RandomUtils.GetRandom(6, 10);
        var numCount = RandomUtils.GetRandom(1, 3);
        var alphaStr = GenerateRandomString(passLen - numCount);
        var numStr = GenerateString(Numbers, numCount);
        var pass = alphaStr + numStr;
        return Shuffle(pass);
    }

    private static string GenerateStrongPassword()
    {
        var lowerCharCount = RandomUtils.GetRandom(2, 5);
        var upperCharCount = RandomUtils.GetRandom(2, 5);
        var numCount = RandomUtils.GetRandom(2, 4);
        var spCharCount = RandomUtils.GetRandom(2, 4);

        var lowerAlphaStr = GenerateString(LowerAlpha, lowerCharCount);
        var upperAlphaStr = GenerateString(UpperAlpha, upperCharCount);
        var spCharStr = GenerateString(SpecialChars, spCharCount);
        var numStr = GenerateString(Numbers, numCount);
        var pass = lowerAlphaStr + upperAlphaStr + spCharStr + numStr;
        return Shuffle(pass);
    }

    private static string GenerateStrongerPassword()
    {
        var lowerCharCount = RandomUtils.GetRandom(5, 12);
        var upperCharCount = RandomUtils.GetRandom(4, 8);
        var numCount = RandomUtils.GetRandom(4, 6);
        var spCharCount = RandomUtils.GetRandom(4, 6);

        var lowerAlphaStr = GenerateString(LowerAlpha, lowerCharCount);
        var upperAlphaStr = GenerateString(UpperAlpha, upperCharCount);
        var spCharStr = GenerateString(SpecialChars, spCharCount);
        var numStr = GenerateString(Numbers, numCount);
        var pass = lowerAlphaStr + upperAlphaStr + spCharStr + numStr;
        return Shuffle(Shuffle(pass));
    }

    public enum PasswordComplexity
    {
        Simple, Medium, Strong, Stronger
    }
}

【讨论】:

    【解决方案3】:

    我为您编写此代码。您可以复制并使用它。我所有的代码都只是一种方法,你可以传递适当的参数,它会给你一个完全随机的密码。我在回答你的问题之前测试了几次,效果很好。

    private string GeneratePassword(bool useCapitalLetters, bool useSmallLetters, bool useNumbers, bool useSymbols, int passLenght)
        {
            Random random = new Random();
    
            StringBuilder password = new StringBuilder(string.Empty);
    
            //This for loop is for selecting password chars in order 
            for (int i = 0;;)
            {
                if (useCapitalLetters)
                {
                    password.Append((char)random.Next(65, 91)); //Capital letters 
                    ++i; if (i >= passLenght) break;
                }
                if (useSmallLetters)
                {
                    password.Append((char)random.Next(97, 122)); //Small letters
                    ++i; if (i >= passLenght) break;
                }
                if (useNumbers)
                {
                    password.Append((char)random.Next(48, 57)); //Number letters
                    ++i; if (i >= passLenght) break;
                }
                if (useSymbols)
                {
                    password.Append((char)random.Next(35, 38)); //Symbol letters
                    ++i; if (i >= passLenght) break;
                }
            }
    
            //This for loop is for disordering password characters
            for (int i = 0; i < password.Length; ++i)
            {
                int randomIndex1 = random.Next(password.Length);
                int randomIndex2 = random.Next(password.Length);
                char temp = password[randomIndex1];
                password[randomIndex1] = password[randomIndex2];
                password[randomIndex2] = temp;
            }
    
            return password.ToString();
        }
    

    【讨论】:

      【解决方案4】:

      一个完全随机化字符并使用字符的最大重复的答案,我添加了一个随机字符串函数:

              const int Maximum_Identical = 2; // Max number of identical characters in a row 
              const string lower_chars = "abcdefghijklmnopqrstuvwxyz"; // lower case chars
              const string capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //capital chars
              const string numbers = "0123456789"; //numbers
              const string symbols = @"!#$%&*@\"; //symbols
              int lenght = 6; //
      
              bool lowercase = true, capital=true, num=true, sym=true;
      
              List<char[]> PasswordSet = new List<char[]>();
              List<char[]> charSet = new List<char[]>();
              List<int[]> countSet = new List<int[]>();
      
              if (lowercase) charSet.Add(lower_chars.ToArray());
              if (capital) charSet.Add(capital_chars.ToArray());
              if (num) charSet.Add(numbers.ToArray());
              if (sym) charSet.Add(symbols.ToArray());
      
              foreach(var c in charSet)
                  countSet.Add(new int[c.Length]);
      
              Random rdm = new Random();
              //we create alist with each type with a length char (max repeat char included)
              for(int i = 0; i < charSet.Count;i++)
              {
                  var lng = 1;
                  var p0 = "";
                  while (true)
                  {
                      var ind = rdm.Next(0, charSet[i].Length);
                      if (countSet[i][ind] < Maximum_Identical )
                      {
                          countSet[i][ind] += 1;
                          lng++;
                          p0 += charSet[i][ind];
                      }
                      if (lng == lenght) break;
                  }
                  PasswordSet.Add(p0.ToArray());
              }
      
              //generate a password with the desired length with at less one char in desired type,
              //and we choose randomly in desired type to complete the length of password
              var password = "";
              for(int i = 0; i < lenght; i++)
              {
                  char p;
                  if (i < PasswordSet.Count)
                  {                   
                      int id;
                      do
                      {
                          id = rdm.Next(0, PasswordSet[i].Length);
                          p = PasswordSet[i][id];
                      } while (p == '\0');
                      password += p;
                      PasswordSet[i][id] = '\0';
                  }
                  else
                  {
                      int id0;
                      int id1;
                      do
                      {
                          id0 = rdm.Next(0, PasswordSet.Count);
                          id1 = rdm.Next(0, PasswordSet[id0].Length);
                          p = PasswordSet[id0][id1];
                      } while (p == '\0');
                      password += p;
                      PasswordSet[id0][id1] = '\0';
                  }
              }
      
              //you could shuffle the final password
              password = Shuffle.StringMixer(password);
      

      洗牌函数:

      static class Shuffle
      {
          static System.Random rnd = new System.Random();
      
          static void Fisher_Yates(int[] array)
          {
              int arraysize = array.Length;
              int random;
              int temp;
      
              for (int i = 0; i < arraysize; i++)
              {
                  random = i + (int)(rnd.NextDouble() * (arraysize - i));
      
                  temp = array[random];
                  array[random] = array[i];
                  array[i] = temp;
              }
          }
      
          public static string StringMixer(string s)
          {
              string output = "";
              int arraysize = s.Length;
              int[] randomArray = new int[arraysize];
      
              for (int i = 0; i < arraysize; i++)
              {
                  randomArray[i] = i;
              }
      
              Fisher_Yates(randomArray);
      
              for (int i = 0; i < arraysize; i++)
              {
                  output += s[randomArray[i]];
              }
      
              return output;
          }
      }
      

      【讨论】:

        【解决方案5】:

        你去吧:

                string[] charList =
                {
                    "abcdefghijklmnopqrstuvwxyz",
                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                    "0123456789",
                    "@\"!#$%&*@\\"
                };
        
                int desiredPasswordLength = 12;
                var randomNumberGenerator = new Random();
                string generatedPassword = "";
        
                for (int i = randomNumberGenerator.Next() % 4; desiredPasswordLength > 0; i = (i+1) % 4)
                {
        
                    var takeRandomChars = randomNumberGenerator.Next() % 3;
                    for (int j = 0; j < takeRandomChars; j++)
                    {
                        var randomChar = randomNumberGenerator.Next() % charList[i].Length;
                        char selectedChar = charList[i][randomChar % charList[i].Length];
                        generatedPassword = string.Join("", generatedPassword, selectedChar);
                    }
        
                    desiredPasswordLength -= takeRandomChars;
                }
        
                Console.WriteLine("Generated password: {0}",generatedPassword);
        

        【讨论】:

          猜你喜欢
          • 2020-12-28
          • 1970-01-01
          • 2022-10-06
          • 2022-09-23
          • 2023-04-01
          • 1970-01-01
          • 2021-07-01
          • 2010-12-02
          • 2016-08-18
          相关资源
          最近更新 更多