关于C#:生成随机密码

 2019-05-06 

Generating Random Passwords

当我们网站上的一个用户丢失了他的密码并进入丢失的密码页面时,我们需要给他一个新的临时密码。我真的不介意这是多么随机,或者如果它符合所有"需要"的强密码规则,我只想给他们一个密码,他们可以稍后更改。

该应用程序是用C语言编写的Web应用程序。所以我在考虑如何卑鄙地使用guid的一部分。即

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

Suggesstions?思想?


总是有System.Web.Security.Membership.GeneratePassword(int length, int numberOfNonAlphanumericCharacters


1
2
3
4
5
6
7
8
9
10
11
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();
}

这有一个很好的好处,就是能够从可用字符列表中为生成的密码进行选择(例如,仅数字、仅大写或仅小写等)。


我的代码的主要目标是:

  • 弦的分布几乎是一致的(不关心微小的偏差,只要它们很小)
  • 它为每个参数集输出超过数十亿个字符串。如果您的prng只生成20亿(31位熵)的不同值,那么生成8个字符的字符串(大约47位熵)是没有意义的。
  • 它是安全的,因为我希望人们将它用于密码或其他安全令牌。
  • 第一个属性是通过对字母大小取64位值模来实现的。对于小字母(如问题中的62个字符),这会导致可忽略的偏差。第二和第三属性是通过使用RNGCryptoServiceProvider而不是System.Random实现的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    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个字符、字母数字字符串的答案的副本)


    以下是我如何生成随机令牌:

    1
    2
    3
    4
    5
    6
    7
    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中发出的所有值,并且生成的字符是无论你在哪里发送或存储这个。例如,使用Unicode往往会提供大量的中文字符。使用base-64可以保证广泛兼容的字符集,而且只要使用合适的哈希算法,这样的字符串的特性就不会降低它的安全性。


    这要大得多,但我认为它看起来更全面一些:http://www.obviex.com/samples/password.aspx

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    ///////////////////////////////////////////////////////////////////////////////
    // 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
    ///////////////////////////////////////////////////////////////////////////////


    我知道这是一个旧的线程,但我有一个相当简单的解决方案供某人使用。易于实现、易于理解和验证。

    考虑以下要求:

    I need a random password to be generated which has at least 2 lower-case letters, 2 upper-case letters and 2 numbers. The password must also be a minimum of 8 characters in length.

    以下正则表达式可以验证此情况:

    1
    ^(?=\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,}$

    它不在这个问题的范围之内——但是regex是基于lookahead/lookbehind和lookaround的。

    以下代码将创建一组符合此要求的随机字符:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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);

    }

    要满足上述要求,只需调用以下命令:

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

    代码以一个无效字符("!")开头,这样字符串的长度就可以注入新字符。

    然后,它从1循环到所需的小写字符,在每次迭代中,从小写列表中获取一个随机项,并将其注入字符串中的随机位置。

    然后,它对大写字母和数字重复循环。

    这将返回长度为lowercase + uppercase + numerics的字符串,其中所需计数的小写、大写和数字字符已按随机顺序排列。


    对于这类密码,我倾向于使用一个可能生成更容易"使用"的密码的系统。短,通常由可发音的片段和一些数字组成,没有字符间的歧义(这是0还是O?A 1还是I??)有点像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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;

    (直接在浏览器中键入,因此只能用作指导原则。另外,添加更多单词)。


    我不喜欢membership.generatepassword()创建的密码,因为它们太难看,而且有太多的特殊字符。

    此代码生成一个10位数的密码,不太难看。

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

    当然,我可以使用一个regex来做所有的替换,但是这在IMO中更易于阅读和维护。


    我创建了一个使用RNGCryptoServiceProvider的类,它是灵活的。例子:

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


    我一直对内置的密码生成器Keepass非常满意。由于keepass是一个.NET程序,并且是开源的,所以我决定稍微深入研究一下代码。最后,我引用了keepass.exe(标准应用程序安装中提供的副本),作为我项目中的参考,并编写下面的代码。你可以看到基帕斯有多灵活。您可以指定长度,包括/不包括哪些字符等…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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();
        }

    我创建了类似于成员资格提供程序中可用的方法。如果您不想在某些应用程序中添加Web引用,那么这非常有用。

    它很好用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    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;
        }


    这是我很快整理出来的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        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;
        }

    我喜欢看生成密码,就像生成软件密钥一样。您应该从一系列遵循良好实践的字符中进行选择。接受@radu094的回答,并根据良好实践进行修改。不要把每个字母都放在字符数组中。有些信件在电话里很难说清楚。

    您还应该考虑对生成的密码使用校验和,以确保它是由您生成的。实现这一点的一个好方法是使用luhn算法。


    在我的网站上,我使用这种方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        //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


    我再加一个不明智的答案。

    我有一个用例,在这个用例中,我需要随机的密码来进行机器通信,所以我对人的可读性没有任何要求。在我的项目中,我也没有访问Membership.GeneratePassword的权限,也不想添加依赖项。

    我很确定Membership.GeneratePassword正在做类似的事情,但是在这里您可以调整要从中提取的字符池。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    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();
        }
    }

    以及一些示例输出:

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

    抢先投诉使用Random:随机性的主要来源仍然是加密RNG。即使你可以确定地预先决定从Random出来的序列(假设它只产生1),你仍然不知道下一个将被选择的字符(尽管这会限制可能性的范围)。

    一个简单的扩展是向不同的字符集添加权重,这可以简单到增加最大值和通过案例添加下降来增加权重。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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 dice单词列表实现了一个提示系统。


    在已接受的答案中添加了一些补充代码。它改进了只使用随机答案,并允许一些密码选项。我还喜欢keepass答案中的一些选项,但不想在我的解决方案中包含可执行文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    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个字符的字符串。

    1
    2
    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)]; }))

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     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();
        }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    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;
        }


    这个很短,对我很有用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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();
    }


    插入计时器:timer1,2个按钮:button1,button2,1个文本框:textbox 1,和一个组合框:combox1。确保您声明:

    1
    int count = 0;

    源代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     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;
            }
        }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    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;



    }