Génération de mots de passe aléatoires

229

Lorsqu'un utilisateur de notre site perd son mot de passe et se rend sur la page Mot de passe perdu, nous devons lui donner un nouveau mot de passe temporaire. Cela ne me dérange pas vraiment à quel point c'est aléatoire, ou si cela correspond à toutes les règles de mot de passe fort "nécessaires", tout ce que je veux faire, c'est leur donner un mot de passe qu'ils pourront changer plus tard.

L'application est une application Web écrite en C #. donc je pensais être méchant et opter pour la voie facile d'utiliser une partie d'un Guid. c'est à dire

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

Suggesstions? pensées?

FryHard
la source
12
Quelques bonnes solutions ici, mais un petit conseil: ne générez pas de mots de passe contenant l'un de ces caractères: Oo0Ili (vous voyez pourquoi) :)
stian.net
2
J'ai ajouté une réponse qui utilise KeePass comme générateur de mot de passe, et parmi les nombreuses options exposées, j'ai également inclus l'option d'exclure les caractères similaires, comme mentionné par @ stian.net.
Peter

Réponses:

570

Il y en a toujours System.Web.Security.Membership.GeneratePassword(int length, int numberOfNonAlphanumericCharacters) .

Rik
la source
7
Je ne savais pas que le Framework avait une telle méthode! Impressionnant! Échangerai mon code actuel pour cela!
FryHard
35
Je l'ai trouvé après avoir passé près d'une journée à perfectionner mon propre code pw gen. Image comment je me suis senti;)
Rik
16
AFAIK cette méthode ne génère pas de mot de passe conforme à une politique de mot de passe sur le domaine, elle n'est donc pas adaptée à chaque utilisation.
teebot
19
Le principal problème avec cette solution est que vous ne pouvez pas contrôler le jeu de caractères, vous ne pouvez donc pas éliminer les caractères visuellement ambigus (0oOl1i! |) Qui peuvent être vraiment importants dans la pratique.
David Hammond
20
Quelque chose pour ASP.NET Core?
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();
}

Cela a un bon avantage de pouvoir choisir parmi une liste de caractères disponibles pour le mot de passe généré (par exemple, chiffres uniquement, uniquement en majuscules ou uniquement en minuscules, etc.)

Radu094
la source
2
cette méthode (base 62) est supérieure au GUID (base 16) sur la force: une chaîne hexadécimale de 8 caractères équivaut à une chaîne alphanumérique de 4-5 caractères
Jimmy
57
Randomn'est pas cryptographiquement sécurisé; System.Security.Cryptography.RNGCryptoServiceProviderest un meilleur choix.
anaximander
3
Cela générerait le même mot de passe à chaque appel de la méthode, car la classe Random est instanciée à chaque fois. Cela pourrait être sécurisé en retirant Random de cette méthode et en réutilisant l'instance.
Jon
6
Non, ce ne serait pas le cas. À moins que deux personnes décident de changer les mots de passe en même temps.
Radu094
10
citation de la question: ne vous souciez pas "si cela correspond à toutes les règles de mot de passe fort" nécessaires "... merci d'avoir voté contre cette réponse
Radu094
35

Les principaux objectifs de mon code sont:

  1. La distribution des cordes est presque uniforme (ne vous souciez pas des écarts mineurs, tant qu'ils sont petits)
  2. Il génère plus de quelques milliards de chaînes pour chaque ensemble d'arguments. Générer une chaîne de 8 caractères (~ 47 bits d'entropie) n'a aucun sens si votre PRNG ne génère que 2 milliards (31 bits d'entropie) de valeurs différentes.
  3. C'est sécurisé, car je m'attends à ce que les gens l'utilisent pour les mots de passe ou autres jetons de sécurité.

La première propriété est obtenue en prenant une valeur de 64 bits modulo la taille de l'alphabet. Pour les petits alphabets (comme les 62 caractères de la question), cela conduit à un biais négligeable. Les deuxième et troisième propriétés sont obtenues en utilisant RNGCryptoServiceProviderau lieu de 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);
}

(Ceci est une copie de ma réponse à Comment puis-je générer des chaînes alphanumériques aléatoires à 8 caractères en C #? )

CodesInChaos
la source
1
Si UInt64.MaxValue n'est pas divisible de manière égale par characterArray.Length, les caractères sélectionnés de manière aléatoire ne seront pas distribués de manière égale (bien que ce soit un très petit effet).
Jeff Walker Code Ranger
1
@JeffWalkerCodeRanger C'est pourquoi j'ai dit un biais négligeable, pas aucun biais. Même avec un pétaoctet de sortie, vous avez moins de 1% pour le distinguer d'un générateur de chaînes parfaitement impartial. La complexité supplémentaire de l'impartialité parfaite ne vaut clairement pas le gain plutôt théorique de l'aléatoire ici.
CodesInChaos
9
Pour ceux qui utilisent .NET Core, remplacez "new RNGCryptoServiceProvider (). GetBytes (bytes);" avec "System.Security.Cryptography.RandomNumberGenerator.Create (). GetBytes (bytes);"
NPNelson
24
public string GenerateToken(int length)
{
    using (RNGCryptoServiceProvider cryptRNG = new RNGCryptoServiceProvider())
    {
        byte[] tokenBuffer = new byte[length];
        cryptRNG.GetBytes(tokenBuffer);
        return Convert.ToBase64String(tokenBuffer);
    }
}

(Vous pouvez également avoir la classe où cette méthode réside implémenter IDisposable, conserver une référence à la RNGCryptoServiceProvider, et la supprimer correctement, pour éviter de l'instancier à plusieurs reprises.)

Il a été noté que comme cela renvoie une chaîne en base 64, la longueur de sortie est toujours un multiple de 4, avec l'espace supplémentaire utilisé =comme caractère de remplissage. Le lengthparamètre spécifie la longueur du tampon d'octets, pas la chaîne de sortie (et n'est donc peut-être pas le meilleur nom pour ce paramètre, maintenant j'y pense). Cela contrôle le nombre d'octets d' entropie du mot de passe. Cependant, parce que la base-64 utilise un bloc de 4 caractères pour coder chaque 3 octets d'entrée, si vous demandez une longueur qui n'est pas un multiple de 3, il y aura un "espace" supplémentaire, et il sera utilisé =pour remplir le supplémentaire.

Si vous n'aimez pas utiliser des chaînes de base 64 pour une raison quelconque, vous pouvez remplacer l' Convert.ToBase64String()appel par une conversion en chaîne régulière ou par l'une des Encodingméthodes; par exemple. Encoding.UTF8.GetString(tokenBuffer)- assurez-vous simplement de choisir un jeu de caractères qui peut représenter la gamme complète de valeurs provenant du RNG, et qui produit des caractères compatibles avec l'endroit où vous envoyez ou stockez cela. L'utilisation d'Unicode, par exemple, tend à donner beaucoup de caractères chinois. L'utilisation de la base 64 garantit un ensemble de caractères largement compatible, et les caractéristiques d'une telle chaîne ne devraient pas la rendre moins sûre tant que vous utilisez un algorithme de hachage décent.

anaximandre
la source
Je pense que vous voulez mettre tokenBuffer là où vous avez linkBuf.
PIntag
Lorsque j'utilise ce code et que je passe une longueur de 10, la chaîne renvoyée fait toujours 16 caractères et les 2 derniers caractères sont toujours "==". Est-ce que je l'utilise mal? La longueur est-elle spécifiée en hexadécimal?
PIntag
1
La longueur spécifiée est le nombre d'octets de caractère aléatoire (ou "entropie", comme on l'appelle techniquement). Cependant, la valeur renvoyée est codée en base 64, ce qui signifie qu'en raison du fonctionnement du codage en base 64, la longueur de sortie est toujours un multiple de 4. Parfois, c'est plus de caractères qu'il n'en faut pour coder tous les caractères, donc il utilise = caractères pour compléter le reste.
anaximander
1
RNGCryptoServiceProvider est un IDisposable, donc je le mettrais en œuvre avec le modèle using (c'est-à-dire en utilisant (var cryptRNG = new RNGCryptoServiceProvider ()) {...})
kloarubeek
@kloarubeek Un point valide et une bonne suggestion. J'ai ajouté cela à mon exemple de code.
anaximander
20

C'est beaucoup plus grand, mais je pense que cela semble un peu plus complet: 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
///////////////////////////////////////////////////////////////////////////////
GEOCHET
la source
2
Il s'avère que le cadre le soutient. J'accepte donc plutôt cette réponse!
FryHard
1
Générer seulement 2 ^ 31 mots de passe différents, même avec des tailles de sortie longues, est un peu faible. Cela pourrait suffire contre les attaques en ligne, mais certainement trop petit pour les attaques hors ligne. => Je ne recommanderais pas cela.
CodesInChaos
C'est toujours une bonne réponse car la prise en charge «intégrée» est vraiment l'appartenance, et si vous avez décidé de ne pas utiliser l'appartenance à ASP.NET? Cela fonctionne toujours, car la dépendance est System.Web.dll, mais c'est un peu gênant car la méthode n'est pas autonome. @GEOCHET: Merci d'avoir posté cette alternative.
Chris Gomez
8

Je sais que c'est un vieux fil, mais j'ai ce qui pourrait être une solution assez simple à utiliser. Facile à mettre en œuvre, facile à comprendre et facile à valider.

Tenez compte de l'exigence suivante:

J'ai besoin d'un mot de passe aléatoire à générer qui comprend au moins 2 lettres minuscules, 2 lettres majuscules et 2 chiffres. Le mot de passe doit également comporter au moins 8 caractères.

L'expression régulière suivante peut valider ce cas:

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

Cela sort du cadre de cette question - mais l'expression rationnelle est basée sur lookahead / lookbehind et lookaround .

Le code suivant créera un ensemble aléatoire de caractères correspondant à cette exigence:

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

}

Pour répondre à l'exigence ci-dessus, appelez simplement le suivant:

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

Le code commence par un caractère non valide ( "!") - de sorte que la chaîne a une longueur dans laquelle de nouveaux caractères peuvent être injectés.

Il boucle ensuite de 1 au nombre de caractères en minuscules requis et, à chaque itération, récupère un élément aléatoire de la liste en minuscules et l'injecte à un emplacement aléatoire dans la chaîne.

Il répète ensuite la boucle pour les lettres majuscules et pour les chiffres.

Cela vous donne des chaînes de longueur = lowercase + uppercase + numericsdans lesquelles les caractères minuscules, majuscules et numériques du compte que vous voulez ont été placés dans un ordre aléatoire.

Troy Alford
la source
3
Ne pas utiliser System.Randompour des choses critiques pour la sécurité comme les mots de passe. UtilisationRNGCryptoServiceProvider
CodesInChaos
lowers[random.Next(lowers.Length - 1)].ToString() Ce code ne générera jamais de «z». random.Next produit des entiers inférieurs au nombre fourni, vous ne devez donc pas soustraire celui supplémentaire de la longueur.
notbono
6

Pour ce type de mot de passe, j'ai tendance à utiliser un système susceptible de générer plus facilement des mots de passe "utilisés". Court, souvent composé de fragments prononçables et de quelques nombres, et sans ambiguïté intercaractère (est-ce un 0 ou un O? A 1 ou un I?). Quelque chose comme

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;

(Tapé directement dans le navigateur, utilisez-le uniquement à titre indicatif. Ajoutez également d'autres mots).

Adam Wright
la source
6

Je n'aime pas les mots de passe créés par Membership.GeneratePassword (), car ils sont trop laids et ont trop de caractères spéciaux.

Ce code génère un mot de passe à 10 chiffres pas trop laid.

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

Bien sûr, je pourrais utiliser un Regex pour faire tous les remplacements, mais cela est plus lisible et maintenable IMO.

Matt Frear
la source
2
Un GUID ne doit pas être
utilisé
3
Si vous allez utiliser cette méthode, vous pouvez utiliser .ToString ("N") et vous n'aurez pas à remplacer le "-". Il n'est pas non plus nécessaire de remplacer "l", car ce n'est pas un chiffre hexadécimal.
JackAce
Voyez pourquoi vous avez fait ça. J'avais juste besoin d'un mot de passe de courte durée (moins d'une journée) qui ne devait pas être trop unique par utilisateur. Tirer les uns et les zéros est un excellent moyen de supprimer la confusion. J'ai également déplacé le mien en majuscules, puis j'ai réduit la longueur à 6. Comme la suggestion «N» aussi. Merci!
Bill Noel
6

J'ai créé cette classe qui utilise RNGCryptoServiceProvider et elle est flexible. Exemple:

var generator = new PasswordGenerator(minimumLengthPassword: 8,
                                      maximumLengthPassword: 15,
                                      minimumUpperCaseChars: 2,
                                      minimumNumericChars: 3,
                                      minimumSpecialChars: 2);
string password = generator.Generate();
Alex Siepman
la source
C'est super, quelle est la licence sur cette classe? Puis-je l'utiliser?
codeulike
Utilisez-le comme vous le souhaitez!
Alex Siepman
3

J'ai créé cette méthode similaire à celle disponible dans le fournisseur d'adhésion. Ceci est utile si vous ne souhaitez pas ajouter la référence Web dans certaines applications.

Cela fonctionne très bien.

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;
    }
Hugo
la source
6
Ne pas utiliser System.Randompour des choses critiques pour la sécurité comme les mots de passe. UtilisationRNGCryptoServiceProvider
CodesInChaos
3

J'ai toujours été très satisfait du générateur de mots de passe intégré à KeePass. Étant donné que KeePass est un programme .Net et open source, j'ai décidé de creuser un peu autour du code. J'ai fini par referncer KeePass.exe, la copie fournie dans l'installation standard de l'application, comme référence dans mon projet et écrire le code ci-dessous. Vous pouvez voir à quel point il est flexible grâce à KeePass. Vous pouvez spécifier la longueur, les caractères à inclure / ne pas inclure, etc ...

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();
    }
Peter
la source
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;
    }
saeed Ahmad
la source
Veuillez expliquer votre réponse
Linus
1
Cette fonction fonctionne très bien avec quelques modifications. 1. Ajout d'entropie si vous effectuez plusieurs appels à la fois. Cela signifie appelé Sleep () ou une autre fonction provoquant l'entropie entre les appels. 2. Augmentez le nombre et le caractère aléatoire des caractères source. J'ai créé une série de mots de passe de 500 caractères avec keypass à l'exclusion d'un tas de caractères similaires et autres échappables que je ne voulais pas traiter et j'ai utilisé la chaîne de 2000 caractères résultante. Le caractère aléatoire après seulement 100 ms d'entropie était plutôt bon.
Wizengamot
2

Je vais ajouter une autre réponse mal avisée au pot.

J'ai un cas d'utilisation où j'ai besoin de mots de passe aléatoires pour la communication machine-machine, donc je n'ai aucune exigence de lisibilité humaine. Je n'ai pas non plus accès à Membership.GeneratePassworddans mon projet, et je ne veux pas ajouter la dépendance.

Je suis assez certain de Membership.GeneratePasswordfaire quelque chose de similaire à cela, mais ici, vous pouvez régler les pools de personnages à partir desquels puiser.

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

Et un exemple de sortie:

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

Pour anticiper les plaintes concernant l'utilisation de Random: La principale source d'aléatoire est toujours le crypto RNG. Même si vous pouviez prédéterminer de manière déterministe la séquence qui sortait Random(disons qu'elle ne produisait que 1), vous ne sauriez toujours pas le prochain caractère qui serait choisi (bien que cela limiterait la gamme de possibilités).

Une extension simple serait d'ajouter une pondération aux différents jeux de caractères, ce qui pourrait être aussi simple que d'augmenter la valeur maximale et d'ajouter des cas de chute pour augmenter le poids.

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

Pour un générateur de mot de passe aléatoire plus humaniste, j'ai une fois implémenté un système d'invite utilisant la liste de mots de dés EFF .

kitsu.eb
la source
1

J'aime regarder la génération de mots de passe, tout comme la génération de clés logicielles. Vous devez choisir parmi un tableau de caractères qui suivent une bonne pratique. Prenez ce que @ Radu094 a répondu et modifiez-le pour suivre les bonnes pratiques. Ne placez pas chaque lettre dans le tableau de caractères. Certaines lettres sont plus difficiles à dire ou à comprendre par téléphone.

Vous devez également envisager d'utiliser une somme de contrôle sur le mot de passe généré pour vous assurer qu'il a été généré par vous. Une bonne façon d'y parvenir est d'utiliser l' algorithme LUHN .

Dale Ragan
la source
1

Voici ce que j'ai rassemblé rapidement.

    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;
    }
Skyler Campbell
la source
1

J'utilise ce code pour générer un mot de passe avec une composition équilibrée d'alphabet, de caractères numériques et non alphanumériques.

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;
    }
Roohi Ali
la source
0

C'est court et ça fonctionne très bien pour moi.

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();
}
user1058637
la source
Cela peut "fonctionner", mais ce n'est certainement pas sûr. Les mots de passe doivent être sécurisés.
CodesInChaos
Je pense que les mots de passe aléatoires sont des mots de passe temporaires. Ne voyez pas pourquoi ils doivent être sécurisés, et même s'ils le font, vous pouvez ajouter des chiffres et des caractères spéciaux dans la plage.
user1058637
1
L'ajout de chiffres et de caractères spéciaux n'améliore pas la sécurité si vous les générez à l'aide d'un PRNG prévisible. Si vous savez quand un mot de passe a été généré, vous pouvez le limiter à quelques candidats seulement.
CodesInChaos
0

Sur mon site Web, j'utilise cette méthode:

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

Modifiez la chaîne _SymbolsAllde votre liste de tableaux.

GRUNGER
la source
Comme déjà indiqué dans la description de l'édition. Si vous créez un lien vers votre site Web sans qu'il s'agisse d'une référence de code, vous faites uniquement de la publicité, ce qui le rend spam. Veuillez donc supprimer ce lien de votre réponse.
Bowdzone
0

Ajout d'un code supplémentaire à la réponse acceptée. Il améliore les réponses en utilisant simplement aléatoire et permet certaines options de mot de passe. J'ai également aimé certaines des options de la réponse KeePass mais je ne voulais pas inclure l'exécutable dans ma solution.

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

Ce fut le premier lien lorsque j'ai cherché à générer des mots de passe aléatoires et ce qui suit est hors de portée pour la question actuelle, mais pourrait être important à considérer.

  • Basé sur l'hypothèse qui System.Web.Security.Membership.GeneratePasswordest cryptographiquement sécurisée avec un minimum de 20% des caractères non alphanumériques.
  • Je ne sais pas si la suppression de caractères et l'ajout de chaînes est considéré comme une bonne pratique dans ce cas et fournit suffisamment d'entropie.
  • Pourrait envisager d'implémenter d'une certaine manière avec SecureString pour le stockage sécurisé des mots de passe en mémoire.
Mat
la source
Pour info, vous n'auriez pas besoin d'inclure le fichier exécutable KeyPass, car il est open source (le code source est disponible en téléchargement ici )
Alex Klaus
0

validChars peut être n'importe quelle construction, mais j'ai décidé de sélectionner en fonction des plages de code ascii en supprimant les caractères de contrôle. Dans cet exemple, il s'agit d'une chaîne de 12 caractères.

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)]; }))
Sean
la source
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();
    }
akshay tilekar
la source
Les réponses au code ne sont pas encouragées car elles ne fournissent pas beaucoup d'informations aux futurs lecteurs, veuillez fournir des explications sur ce que vous avez écrit
WhatsThePoint
Crée le même mot de passe encore et encore. Besoin d'avoir une instance d' Randomaussi statique
trailmax
Veuillez noter que cette réponse générera le même mot de passe si elle est appelée plusieurs fois de suite !!! Il faut ajouter de l'entropie entre les appels si vous souhaitez utiliser la fonction pour attribuer des mots de passe à l'aide de code à plusieurs enregistrements à la fois. Toujours utile quand même ....
Wizengamot
0

Ce package vous permet de générer un mot de passe aléatoire tout en indiquant couramment les caractères qu'il doit contenir (si nécessaire):

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

Exemple:

var pwd = new Password().IncludeLowercase().IncludeUppercase().IncludeSpecial();
var password = pwd.Next();
Johan Maes
la source
0

Si vous souhaitez utiliser la génération de nombres aléatoires cryptographiquement sécurisée utilisée par System.Web.Security.Membership.GeneratePassword mais souhaitez également restreindre le jeu de caractères aux caractères alphanumériques, vous pouvez filtrer le résultat avec une expression régulière:

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);
}
samgak
la source
-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;



}
Ercan ILIK
la source
Pourriez-vous expliquer ce que fait votre code et pourquoi? De l'avis
Wai Ha Lee
Seules les réponses sans explication sont susceptibles d'être supprimées.
Tour
-4

Insérez un Timer: timer1, 2 boutons: button1, button2, 1 textBox: textBox1 et un comboBox: comboBox1. Assurez-vous de déclarer:

int count = 0;

Code source:

 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;
        }
    }
Joe
la source
1
Ne pas utiliser System.Randompour la sécurité.
CodesInChaos