Rastgele Parolalar Oluşturma


229

Sitemizdeki bir kullanıcı şifresini kaybettiğinde ve Kayıp Şifre sayfasına gittiğinde, ona yeni bir geçici şifre vermeliyiz. Bunun ne kadar rasgele olduğunu umursamıyorum ya da tüm "gerekli" güçlü şifre kurallarına uyuyorsa, tek yapmak istediğim onlara daha sonra değiştirebilecekleri bir şifre vermektir.

Uygulama C # ile yazılmış bir Web uygulamasıdır. bu yüzden kaba olmayı ve bir Rehber'in bir kısmını kullanmanın kolay yolunu bulmayı düşünüyordum. yani

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

Suggesstions? düşünceler?


12
Burada birkaç iyi çözüm, ancak küçük bir tavsiye: Şu karakterlerden herhangi birini içeren şifreler üretmeyin: Oo0Ili (nedenini görüyorsunuz) :)
stian.net

2
Bir şifre üreticisi olarak KeePass kullanan bir cevap ekledim ve maruz kalan birçok seçenek arasında, @ stian.net tarafından belirtildiği gibi, benzer karakterleri hariç tutma seçeneğini de dahil ettim.
Peter

Yanıtlar:


570

7
Çerçevenin böyle bir yöntemi olduğunu bilmiyordum! Müthiş! Bunun için mevcut kodumu değiştireceğim!
FryHard

35
Kendi pw gen kodumu mükemmelleştirerek neredeyse bir gün geçirdikten sonra buldum. Nasıl hissettim;)
Rik

16
AFAIK bu yöntem, alan adındaki bir şifre politikasına uygun bir şifre oluşturmaz, bu nedenle her kullanım için uygun değildir.
teebot

19
Bu çözümle ilgili temel sorun, karakter setini kontrol edememenizdir, bu nedenle pratikte gerçekten önemli olabilecek görsel olarak belirsiz karakterleri (0oOl1i! |) Ortadan kaldıramazsınız.
David Hammond

21
İçin bir şey var ASP.NET Coremı?
shashwat

114
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();
}

Bunun, oluşturulan parola için kullanılabilir karakterler listesinden seçim yapabilmesinin iyi bir yararı vardır (örneğin yalnızca rakamlar, yalnızca büyük harf veya yalnızca küçük harf vb.)


2
bu yöntem (taban 62), dayanıklılıktaki GUID'den (taban 16) üstündür: 8 karakterlik bir altıgen dize, 4-5 karakterlik alfasayısal olana eşdeğerdir
Jimmy

57
Randomkriptografik olarak güvenli değildir; System.Security.Cryptography.RNGCryptoServiceProviderdaha iyi bir seçimdir.
anaximander

3
Bu, yöntem her çağrıldığında aynı parolayı oluşturur, çünkü Random sınıfı her seferinde başlatılır. Bu, Random'ı bu yöntemin dışına çıkararak ve örneği yeniden kullanarak güvenli hale getirilebilir.
Jon

6
Hayır. İki kişi aynı saatte şifreleri değiştirmeye karar vermedikçe.
Radu094

10
sorudan alıntı: umurumda değil "tüm" gerekli "güçlü şifre kurallarına uyuyorsa ... ... olsa da bu cevabı aşağıya indirdiğiniz için teşekkürler
Radu094

35

Kodumun ana hedefleri:

  1. Dizelerin dağılımı neredeyse eşittir (küçük oldukları sürece küçük sapmaları umursamayın)
  2. Her bir argüman kümesi için birkaç milyardan fazla karakter dizisi çıkarır. PRNG'niz sadece 2 milyar (31 bit entropi) farklı değerler üretiyorsa, 8 karakterlik bir dize (~ 47 bit entropi) oluşturmak anlamsızdır.
  3. Güvenlidir, çünkü insanların bunu şifreler veya diğer güvenlik belirteçleri için kullanmasını bekliyorum.

Birinci özellik, 64 bitlik bir modulo alfabe boyutu alınarak elde edilir. Küçük harfler için (sorudan gelen 62 karakter gibi) bu ihmal edilebilir bir sapmaya yol açar. İkinci ve üçüncü özellik RNGCryptoServiceProvideryerine kullanılarak elde edilir 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);
}

(Bu cevabım bir kopyasıdır rastgele 8 karakter, C # alfanümerik dizeleri üretebilir nasıl? )


1
UInt64.MaxValue, characterArray.Length tarafından eşit olarak bölünemezse, rastgele seçilen karakterler eşit olarak dağıtılmaz (bu çok küçük bir etki olacaktır).
Jeff Walker Code Ranger

1
@JeffWalkerCodeRanger Bu yüzden ihmal edilebilir önyargı dedim, önyargı yok. Bir petabayt çıkış ile bile, bunu mükemmel bir tarafsız dizgi üreticisinden ayırt etmek için% 1'den daha azına sahipsiniz. Mükemmel çirkinleşmenin ek karmaşıklığı, buradaki rastgelelikte oldukça teorik kazanıma değmez.
CodesInChaos

9
.NET Core kullananların yerine "new RNGCryptoServiceProvider (). GetBytes (bytes);" "System.Security.Cryptography.RandomNumberGenerator.Create (). GetBytes (bayt);"
NPNelson

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

(Ayrıca, bu yöntemin yaşandığı sınıfa sahip olmayan bir sınıfa sahip olabilirsiniz, RNGCryptoServiceProvider tekrar tekrar örneklenmekten kaçınmak ve uygun şekilde imha edebilirsiniz.)

Bu, bir base-64 dizesi döndürdüğü için, çıkış uzunluğunun her zaman 4'ün katı olduğu ve fazladan =bir boşluk karakteri olarak kullanıldığına dikkat edilmelidir. lengthParametre bayt tampon değil, çıkış dize uzunluğunu belirler (ve bu nedenle belki de bu parametre için en iyi isim değil, şimdi bunu düşünüyorum). Bu , şifrenin kaç bayt entropi olduğunu kontrol eder . Ancak, base-64, her 3 baytlık girişi kodlamak için 4 karakterlik bir blok kullandığından, 3'ün katı olmayan bir uzunluk isterseniz, fazladan bir "boşluk" olur =ve ekstra.

Herhangi bir nedenle base-64 dizelerini kullanmaktan hoşlanmıyorsanız, Convert.ToBase64String() aramayı normal dizeye dönüştürmeyle veya Encodingyöntemlerden herhangi biriyle değiştirebilirsiniz ; Örneğin. Encoding.UTF8.GetString(tokenBuffer)- RNG'den çıkan tüm değer aralığını temsil edebilen ve bunu gönderdiğiniz veya sakladığınız her yerle uyumlu karakterler üreten bir karakter kümesi seçtiğinizden emin olun. Örneğin, Unicode kullanmak birçok Çince karakter verme eğilimindedir. Base-64 kullanmak, çok uyumlu bir karakter setini garanti eder ve böyle bir dizenin özellikleri, iyi bir karma algoritması kullandığınız sürece onu daha az güvenli hale getirmemelidir.


LinkBuf'unuzun olduğu yere tokenBuffer koymak istediğinizi düşünüyorum.
PIntag

Bu kodu kullandığımda ve 10 uzunluğunda geçtiğimde, döndürülen dize her zaman 16 karakter uzunluğunda ve son 2 karakter her zaman "==" olur. Yanlış mı kullanıyorum? Uzunluk onaltılı olarak belirtilmiş mi?
PIntag

1
Belirtilen uzunluk rastgele bayt sayısıdır (veya teknik olarak bilindiği gibi "entropi"). Ancak, döndürülen değer base-64 kodludur, bu da base-64 kodlamanın nasıl çalıştığı nedeniyle çıktı uzunluğunun her zaman 4'ün katı olduğu anlamına gelir. Bazen bu, tüm karakterleri kodlamak için gerekenden daha fazla karakterdir, bu nedenle kullanır = geri kalanını doldurmak için karakter.
anaximander

1
RNGCryptoServiceProvider bir IDisposable, bu yüzden kullanarak desen ile uygulamak istiyorum (yani kullanarak (var cryptRNG = yeni RNGCryptoServiceProvider ()) {...})
kloarubeek

@kloarubeek Geçerli bir nokta ve iyi bir öneri. Bunu kod örneğime ekledim.
anaximander

20

Bu çok daha büyük, ama sanırım biraz daha kapsamlı görünüyor: 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
Çerçeve ile buna destek olduğu ortaya çıktı. Bu yüzden cevabı kabul ediyorum!
FryHard

1
Uzun çıktı boyutlarında bile yalnızca 2 ^ 31 farklı parola oluşturmak, düşük tarafta biraz. Çevrimiçi saldırılara karşı yeterli olabilir, ancak çevrimdışı saldırılar için kesinlikle küçük olabilir. => Bunu tavsiye etmem.
CodesInChaos

Bu hala iyi bir yanıt çünkü "yerleşik" destek gerçekten Üyeliktir ve ASP.NET Üyeliğini kullanmamaya karar verdiyseniz ne olur? Bağımlılık System.Web.dll olduğundan hala çalışır, ancak yöntem kendi kendine yetmediği için biraz gariptir. @GEOCHET: Bu alternatifi gönderdiğiniz için teşekkür ederiz.
Chris Gomez

8

Bu eski bir iş parçacığı olduğunu biliyorum, ama birisi kullanmak için oldukça basit bir çözüm olabilir ne var. Uygulaması kolay, anlaşılması kolay ve doğrulaması kolay.

Aşağıdaki gereksinimi göz önünde bulundurun:

En az 2 küçük harf, 2 büyük harf ve 2 rakamdan oluşan rastgele bir parolaya ihtiyacım var. Parola en az 8 karakter uzunluğunda olmalıdır.

Aşağıdaki düzenli ifade bu durumu doğrulayabilir:

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

Bu sorunun kapsamı dışındadır - ancak normal ifade ileriye / geriye ve geriye doğru bakmaktadır. .

Aşağıdaki kod, bu gereksinimle eşleşen rastgele bir karakter kümesi oluşturur:

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);

}

Yukarıdaki gereksinimi karşılamak için aşağıdakileri aramanız yeterlidir:

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

Kod geçersiz bir karakterle başlıyor ("!" ) böylece dizenin içine yeni karakterlerin eklenebileceği bir uzunluk olur.

Daha sonra, 1'den küçük harfli karakterlere kadar döngü yapar ve her yinelemede, küçük harf listesinden rastgele bir öğe alır ve bunu dizede rastgele bir konuma enjekte eder.

Daha sonra büyük harfler ve sayısallar için döngüyü tekrarlar.

Bu lowercase + uppercase + numericssize, istediğiniz sayının küçük harf, büyük harf ve sayısal karakterlerinin rastgele sırada yerleştirildiği uzunluk = dizelerini verir .


3
System.RandomParola gibi güvenlik açısından kritik şeyler için kullanmayın . UseRNGCryptoServiceProvider
CodesInChaos

lowers[random.Next(lowers.Length - 1)].ToString() Bu kod asla bir 'z' üretmez. Sonraki, sağlanan sayıdan daha az tamsayı üretir , bu nedenle bu fazlalığı uzunluktan çıkarmamalısınız .
notbono

6

Bu tür bir şifre için, daha kolay "kullanılmış" şifreler üretmesi muhtemel bir sistem kullanma eğilimindeyim. Kısa, genellikle belirgin parçalardan ve birkaç sayıdan oluşur ve karakterler arası belirsizliğe sahip değildir (bu 0 veya O? A 1 veya I?). Gibi bir şey

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;

(Doğrudan tarayıcıya yazılmıştır, bu yüzden yalnızca yönergeler olarak kullanın. Ayrıca, daha fazla kelime ekleyin).


6

Membership.GeneratePassword () 'in oluşturduğu şifreleri sevmiyorum, çünkü çok çirkin ve çok fazla özel karaktere sahipler.

Bu kod, 10 basamaklı çok çirkin olmayan bir şifre oluşturur.

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

Elbette, tüm yedekleri yapmak için bir Regex kullanabilirim, ancak bu daha okunabilir ve bakımı kolay bir IMO.


2
Bir GUID, kripto PRNG olarak kullanılmamalıdır
CodesInChaos

3
Bu yöntemi kullanacaksanız, .ToString ("N") kullanabilirsiniz ve "-" yerine geçmeniz gerekmez. Onaltılı bir rakam olmadığından "l" yerine geçmeye de gerek yoktur.
JackAce

Bunu neden yaptığınızı tamamen görün. Kullanıcı başına çok özel olması gerekmeyen kısa ömürlü (bir günden az) bir şifreye ihtiyacım vardı. Bunları ve sıfırları dışarı atmak karışıklığı ortadan kaldırmak için harika bir yoldur. Ayrıca benimkini büyük harfe kaydırdım ve sonra uzunluğu 6'ya kestim. 'N' önerisi gibi. Teşekkürler!
Bill Noel

6

RNGCryptoServiceProvider kullanan bu sınıfı oluşturdum ve esnektir. Misal:

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

Harika, o sınıftaki lisans nedir? Kullanabilirmiyim?
codeulike

İstediğiniz gibi kullanın!
Alex Siepman

3

Bu yöntemi üyelik sağlayıcısındakine benzer şekilde oluşturdum. Web başvurusunu bazı uygulamalara eklemek istemiyorsanız bu yararlıdır.

Harika çalışıyor.

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;
    }

6
System.RandomParola gibi güvenlik açısından kritik şeyler için kullanmayın . UseRNGCryptoServiceProvider
CodesInChaos

3

KeePass'ta bulunan şifre üreticisi ile her zaman çok mutlu oldum. KeePass bir .Net programı ve açık kaynak olduğundan, kodu biraz araştırmaya karar verdim. Projemde bir referans olarak ve aşağıdaki kodu yazarak standart uygulama kurulumunda sağlanan kopyası KeePass.exe'yi sadece referncing ile bitirdim. KeePass sayesinde ne kadar esnek olduğunu görebilirsiniz. Uzunluğu, hangi karakterlerin dahil edileceğini / eklenmeyeceğini vb. Belirtebilirsiniz.

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();
    }

2
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;
    }

Lütfen cevabınızı açıklayın
Linus

1
Bu işlev birkaç değişiklikle çok iyi çalışır. 1. Aynı anda birden fazla arama yapıyorsanız entropi eklendi. Bu, aramalar arasında Sleep () veya başka bir entropiye neden fonksiyon olarak adlandırılır. 2. Kaynak karakterlerin sayısını ve rastgele sayısını artırın. Anlaşmak istemediğim benzer ve diğer kaçış karakterleri bir grup hariç tuş geçidi ile 500 karakterlik bir dizi şifre oluşturdum ve ortaya çıkan 2000 karakter dizesini kullandım. Sadece 100 ms Entropi'den sonra rastgelelik oldukça iyiydi.
Wizengamot

2

Tencereye kötü niyetli bir cevap daha ekleyeceğim.

Makine-makine iletişimi için rastgele parolalara ihtiyacım olduğu bir kullanım durumum var, bu yüzden insan tarafından okunabilirlik için herhangi bir gereksinimim yok. Projemde de erişimim Membership.GeneratePasswordyok ve bağımlılığı eklemek istemiyorum.

Buna Membership.GeneratePasswordbenzer bir şey yaptığından oldukça eminim , ancak burada çizilecek karakter havuzlarını ayarlayabilirsiniz.

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();
    }
}

Ve bazı örnek çıktılar:

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

Şunların kullanımı ile ilgili şikayetleri önlemek için Random: Birincil rastgelelik kaynağı hala kripto RNG'dir. Eğer deterministik çıkan dizisini preordain olsaydı bile Random(yalnızca üretilen demek 1(hala alınmayı sonraki kömürü bilemeyiz) gerçi o olur olasılıklar yelpazesini sınırlamak).

Basit bir uzantı, farklı karakter kümelerine ağırlık eklemek, maksimum değeri artırmak ve ağırlığı artırmak için düşme vakaları eklemek kadar basit olabilir.

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;
}

Daha hümanist bir rastgele şifre üreticisi için bir keresinde EFF zar-kelime listesini kullanarak bir bilgi istemi sistemi uyguladım .


1

Parola üretmeyi, tıpkı yazılım anahtarları üretmeyi severim. İyi bir uygulama izleyen bir dizi karakter arasından seçim yapmalısınız. @ Radu094'un yanıtladığı şeyi al ile ve iyi uygulamaları takip etmek için değiştirin. Karakter dizisine her bir harfi koymayın. Bazı harfleri telefonla söylemek veya anlamak daha zordur.

Ayrıca, sizin tarafınızdan oluşturulduğundan emin olmak için oluşturulan parola üzerinde bir sağlama toplamı kullanmayı da düşünmelisiniz. Bunu başarmanın iyi bir yolu LUHN algoritmasını kullanmaktır .


1

İşte hızlı bir şekilde bir araya getirdik.

    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;
    }

1

Bu kodu alfabe, sayısal ve alfasayısal olmayan karakterlerin denge kompozisyonu ile şifre oluşturmak için kullanıyorum.

public static string GeneratePassword(int Length, int NonAlphaNumericChars)
    {
        string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
        string allowedNonAlphaNum = "!@#$%^&*()_-+=[{]};:<>|./?";
        string pass = "";
        Random rd = new Random(DateTime.Now.Millisecond);
        for (int i = 0; i < Length; i++)
        {
            if (rd.Next(1) > 0 && NonAlphaNumericChars > 0)
            {
                pass += allowedNonAlphaNum[rd.Next(allowedNonAlphaNum.Length)];
                NonAlphaNumericChars--;
            }
            else
            {
                pass += allowedChars[rd.Next(allowedChars.Length)];
            }
        }
        return pass;
    }

0

Bu kısa ve benim için harika çalışıyor.

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();
}

"Çalışabilir" ama kesinlikle güvenli değil. Şifrelerin güvenli olması gerekir.
CodesInChaos

Ben rastgele şifreler geçici şifreler olduğunu düşünüyorum. Neden güvende olmaları gerektiğini anlamayın ve öyle olsalar bile, aralığa sayılar ve özel karakterler ekleyebilirsiniz.
user1058637

1
Sayılar ve özel karakterler eklemek, tahmin edilebilir bir PRNG kullanarak oluşturursanız güvenliği artırmaz. Bir parolanın ne zaman oluşturulduğunu biliyorsanız, yalnızca birkaç adayla daraltabilirsiniz.
CodesInChaos

0

Web sitemde bu yöntemi kullanıyorum:

    //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();
    }

_SymbolsAllDizi listeniz için dizeyi düzenleyin.


Düzenleme açıklamasında zaten belirtildiği gibi. Web sitenize bir kod referansı olmadan bağlantı verirseniz, tamamen spam yapan reklamcılık yapıyorsunuz, bu yüzden lütfen bu bağlantıyı yanıtınızdan kaldırın.
Bowdzone

0

Kabul edilen cevaba bazı ek kodlar eklendi. Sadece Rastgele kullanarak cevapları geliştirir ve bazı şifre seçeneklerine izin verir. Ayrıca KeePass cevap bazı seçenekleri sevdim ama benim çözüm yürütülebilir çalıştırmak istemiyordu.

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;
}

Bu, rastgele şifreler oluşturmak için arama yaptığım ilk bağlantıydı ve aşağıdakiler mevcut soru için kapsam dışıdır, ancak dikkate alınması önemli olabilir.

  • Varsayımına dayanarak System.Web.Security.Membership.GeneratePasswordKarakterlerin en az% 20'sinin Alfasayısal Olmayan olmasıyla kriptografik olarak güvenli olduğu .
  • Bu durumda karakterleri kaldırmanın ve dizeleri eklemenin iyi bir uygulama olarak kabul edilip edilmediğinden ve yeterli entropi sağlayıp sağlamadığından emin değilim.
  • Bellekte güvenli parola depolaması için SecureString ile bir şekilde uygulamayı düşünmek isteyebilirsiniz .

FYI, açık kaynak olduğu için KeyPass yürütülebilir dosyasını eklemenize gerek yok (kaynak kodu buradan indirilebilir )
Alex Klaus

0

validChars herhangi bir yapı olabilir, ama ben kontrol karakterleri kaldırma ascii kod aralıkları dayalı seçmeye karar verdi. Bu örnekte, 12 karakterlik bir dizedir.

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

0
 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();
    }

Kod sadece cevaplar öyle değil çünkü gelecek okuyucular için fazla bilgi vermiyorlar, lütfen yazdıklarınıza biraz açıklama yapın
WhatsThePoint

Aynı şifreyi tekrar tekrar oluşturur. RandomStatik olarak örneği olması gerekir
trailmax

Bu cevabın arka arkaya birden fazla kez çağrılırsa aynı şifreyi oluşturacağını lütfen unutmayın !!! Aynı anda birden fazla kayda kod kullanarak şifre atamak için bu işlevi kullanmak istiyorsanız, aramalar arasında Entropi eklenmelidir. Yine de yararlı ....
Wizengamot

0

Bu paket, hangi karakterleri içermesi gerektiğini (gerekirse) akıcı bir şekilde belirtirken rastgele bir şifre oluşturmanıza olanak tanır:

https://github.com/prjseal/PasswordGenerator/

Misal:

var pwd = new Password().IncludeLowercase().IncludeUppercase().IncludeSpecial();
var password = pwd.Next();

0

System.Web.Security.Membership.GeneratePassword tarafından kullanılan kriptografik olarak güvenli rasgele sayı oluşturmayı kullanmak istiyorsanız, ancak karakter kümesini alfasayısal karakterlerle sınırlamak istiyorsanız, sonucu bir normal ifadeyle filtreleyebilirsiniz:

static string GeneratePassword(int characterCount)
{
    string password = String.Empty;
    while(password.Length < characterCount)
        password += Regex.Replace(System.Web.Security.Membership.GeneratePassword(128, 0), "[^a-zA-Z0-9]", string.Empty);
    return password.Substring(0, characterCount);
}

-3
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;



}

Kodunuzun ne yaptığını ve nedenini açıklayabilir misiniz? Yorumdan
Wai Ha Lee

Kodun yalnızca açıklaması olmayan yanıtların silinmesi muhtemeldir.
Kale

-4

Bir Timer: timer1, 2 düğme: button1, button2, 1 textBox: textBox1 ve bir comboBox: comboBox1 ekleyin. Beyan ettiğinizden emin olun:

int count = 0;

Kaynak kodu:

 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
System.RandomGüvenlik için kullanmayın .
CodesInChaos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.