Gerador de senha “Crapcode”

Sep 27 2020

Fiz o Gerador de senha em C #.

Ele solicita ao usuário o comprimento da senha , se contém números , letras minúsculas , letras maiúsculas ou símbolos , e gera uma senha forte a partir de números, letras ou símbolos adicionados aleatoriamente.

Aqui está o código:

using System;

namespace Password_Generator
{
    class Program
    {
        static string Randomize(string Str)
        {
            Random Rand = new Random();

            string Randomized = "";

            while (Randomized.Length < Str.Length)
            {
                Randomized += Str[Rand.Next(0, Str.Length)];
            }

            return Randomized;
        }

        static void Main(string[] args)
        {
            while (true)
            {
                Console.ForegroundColor = ConsoleColor.White;

                Console.Write("\nDo Yout Want a New Password [True], [False]? ");
                Console.ForegroundColor = ConsoleColor.Yellow;
                string NewPasswordStr = Console.ReadLine();
                bool NewPassword;

                while (bool.TryParse(NewPasswordStr, out NewPassword) == false)
                {
                    Console.Clear();

                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("The Given Output is Unconvertable Or it's Value is Unacceptable. Try Again!");

                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write("\nDo Yout Want a New Password [True], [False]? ");

                    Console.ForegroundColor = ConsoleColor.Yellow;
                    NewPasswordStr = Console.ReadLine();
                    Console.ForegroundColor = ConsoleColor.White;
                }

                Console.ForegroundColor = ConsoleColor.White;

                if (NewPassword == true)
                {
                    Console.Clear();

                    Console.Write("Password Length: ");

                    Console.ForegroundColor = ConsoleColor.Yellow;
                    string LenghtStr = Console.ReadLine();
                    int Lenght;

                    while (int.TryParse(LenghtStr, out Lenght) == false || int.Parse(LenghtStr) <= 0)
                    {
                        Console.Clear();

                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("The Given Output is Unconvertable Or it's Value is Unacceptable. Try Again!");

                        Console.ForegroundColor = ConsoleColor.White;
                        Console.Write("\nPassword Length: ");

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        LenghtStr = Console.ReadLine();
                        Console.ForegroundColor = ConsoleColor.White;
                    }

                    Console.ForegroundColor = ConsoleColor.White;

                    Console.Write("\n\nInclude Numbers (0 - 9) [True], [False]: ");

                    Console.ForegroundColor = ConsoleColor.Yellow;
                    string IncludeNumbersStr = Console.ReadLine();
                    bool IncludeNumbers;

                    while (bool.TryParse(IncludeNumbersStr, out IncludeNumbers) == false)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("\nThe Given Output is Unconvertable. Try Again!");

                        Console.ForegroundColor = ConsoleColor.White;
                        Console.Write("\nInclude Numbers (0 - 9) [True], [False]: ");

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        IncludeNumbersStr = Console.ReadLine();
                        Console.ForegroundColor = ConsoleColor.White;
                    }

                    Console.Write("\n\nInclude Lowercase Letters (a - z) [True], [False]: ");

                    Console.ForegroundColor = ConsoleColor.Yellow;
                    string IncludeLowercaseStr = Console.ReadLine();
                    bool IncludeLowercase;

                    while (bool.TryParse(IncludeLowercaseStr, out IncludeLowercase) == false)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("\nThe Given Output is Unconvertable. Try Again!");

                        Console.ForegroundColor = ConsoleColor.White;
                        Console.Write("\nInclude Lowercase Letters (a - z) [True], [False]: ");

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        IncludeLowercaseStr = Console.ReadLine();
                        Console.ForegroundColor = ConsoleColor.White;
                    }

                    Console.ForegroundColor = ConsoleColor.White;

                    Console.Write("\n\nInclude Uppercase Letters (A - Z) [True], [False]: ");

                    Console.ForegroundColor = ConsoleColor.Yellow;
                    string IncludeUppercaseStr = Console.ReadLine();
                    bool IncludeUppercase;

                    while (bool.TryParse(IncludeUppercaseStr, out IncludeUppercase) == false)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("\nThe Given Output is Unconvertable. Try Again!");

                        Console.ForegroundColor = ConsoleColor.White;
                        Console.Write("\nInclude Uppercase Letters (A - X) [True], [False]: ");

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        IncludeUppercaseStr = Console.ReadLine();
                        Console.ForegroundColor = ConsoleColor.White;
                    }

                    Console.ForegroundColor = ConsoleColor.White;

                    Console.Write("\n\nInclude Symbols [True], [False]: ");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    string IncludeSymbolsStr = Console.ReadLine();
                    bool IncludeSymbols;

                    while (bool.TryParse(IncludeSymbolsStr, out IncludeSymbols) == false)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("\nThe Given Output is Unconvertable. Try Again!");

                        Console.ForegroundColor = ConsoleColor.White;
                        Console.Write("\nInclude Symbols [True], [False]: ");

                        Console.ForegroundColor = ConsoleColor.Yellow;
                        IncludeSymbolsStr = Console.ReadLine();
                        Console.ForegroundColor = ConsoleColor.White;
                    }

                    Console.ForegroundColor = ConsoleColor.White;

                    string Password = "";

                    while (Password.Length < Lenght)
                    {
                        Random Rand = new Random();

                        if (IncludeNumbers == true)
                        {
                            Password += ((char)Rand.Next(48, 58)).ToString();
                        }

                        if (Password.Length == Lenght)
                        {
                            break;
                        }

                        if (IncludeLowercase == true)
                        {
                            Password += ((char)Rand.Next(97, 123)).ToString();
                        }

                        if (Password.Length == Lenght)
                        {
                            break;
                        }

                        if (IncludeUppercase == true)
                        {
                            Password += ((char)Rand.Next(97, 123)).ToString().ToUpper();
                        }

                        if (Password.Length == Lenght)
                        {
                            break;
                        }

                        if (IncludeSymbols == true)
                        {
                            Password += ((char)Rand.Next(33, 48)).ToString().ToUpper();
                        }

                        if (Password.Length == Lenght)
                        {
                            break;
                        }
                    }

                    Password = Randomize(Password);

                    Console.WriteLine();

                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                    Console.WriteLine(Password);
                    Console.ForegroundColor = ConsoleColor.White;
                }

                else
                {
                    Environment.Exit(-1);
                }
            }

        }
    }
}

As linhas 221 são demais para isso? Como melhorar isso? Isso é um "crapcode"? Como não escrever crapcode? ....Obrigado!

Respostas

7 radarbob Sep 28 2020 at 10:52

Da documentação da classe MSDN Random

Para gerar um número aleatório criptograficamente seguro, como um que seja adequado para criar uma senha aleatória, use a classe RNGCryptoServiceProvider ou derivar uma classe de System.Security.Cryptography.RandomNumberGenerator.


Rand aleatório = novo aleatório ();

Correção de edição : usando um instantâneo do relógio do sistema, o construtor sem parâmetro acaba usando valores de semente diferentes; a menos que os objetos aleatórios sejam criados tão próximos no tempo que o mesmo relógio seja usado. Dado o mesmo argumento (valor da semente do parâmetro), Randoms diferentes geram a mesma sequência aleatória. fim da edição

Cada Randomobjeto criado com o construtor sem parâmetros irá gerar a mesma sequência de números aleatórios porque o mesmo valor de "semente padrão" é usado todas as vezes. Isso é perfeito para desenvolvimento e teste, mas não em código de produção. Ler a hora do sistema em milissegundos é uma maneira comum de gerar diferentes valores de "semente" para cada chamada do construtor.


Crapcode Code Smell

As dúvidas vagas que você tem sobre o código são tecnicamente chamadas de "cheiro de código", o que significa que parece suspeito por algum motivo - o comprimento "parece" longo para o que está fazendo, neste caso. Pode haver algo errado, talvez não; um "cheiro de código" requer um exame mais minucioso para determinar se algo está de fato errado.

Um cheiro de código que vejo são os vários whileloops de aparência semelhante , cada um procurando por diferentes caracteres necessários. Não quero escrever código difícil de entender por causa de menos linhas. "Menos linhas de código" por si só não é razão para mudar as coisas. Aqui está uma ideia, talvez seja uma melhoria ou talvez não:

Informe ao usuário os caracteres obrigatórios antecipadamente ao solicitar a senha.

Uma string é iterável, você pode "forEach". A Stringé, na verdade, uma matriz de Char, tecnicamente.

forEach (char character in enteredPassword) { ... }

Examine cada personagem para seu tipo. Mantenha uma contagem separada para cada tipo de caractere.

Após o forEachteste de cada contador para o mínimo necessário. Se symbolsfor zero, por exemplo, acrescente "pelo menos um caractere de símbolo é necessário" a uma mensagem de erro.


Para sua informação

Há um velho ditado com um fundo de verdade: se você resolve um problema com uma expressão regular, agora você tem dois problemas


221 linhas são demais para isso

Existem muitas diretrizes, princípios, "ismos", etc. para avaliar a qualidade do código. A contagem de linhas não é um deles.