Generador de contraseñas "Crapcode"
Hice Password Generator en C #.
Se solicita al usuario la longitud de la contraseña , si contiene números , letras minúsculas , letras mayúsculas o símbolos , y genera una contraseña segura de números añadidos al azar, letras o símbolos.
Ahí está el 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);
}
}
}
}
}
¿La línea 221 es demasiado para esto? ¿Cómo mejorarlo? ¿Es esto un "crapcode"? ¿Cómo no escribir crapcode? ....¡Gracias!
Respuestas
De la documentación de la clase aleatoria de MSDN
Para generar un número aleatorio criptográficamente seguro, como uno que sea adecuado para crear una contraseña aleatoria, use la clase RNGCryptoServiceProvider o derive una clase de System.Security.Cryptography.RandomNumberGenerator.
Random Rand = nuevo Random ();
Corrección de edición : usando una instantánea del reloj del sistema, el constructor sin parámetros termina usando diferentes valores de inicialización; a menos que los objetos Random se creen tan cerca en el tiempo que se use la misma hora del reloj. Dado el mismo argumento (valor de semilla del parámetro), diferentes Randoms generan la misma secuencia aleatoria. fin Editar
Cada
Randomobjeto creado con el constructor sin parámetros generará la misma secuencia de números aleatorios porque se usa el mismo valor de "semilla predeterminada" cada vez. Esto es perfecto para desarrollo y prueba, pero no en código de producción. Leer el tiempo del sistema en milisegundos es una forma común de generar diferentes valores de "semilla" para cada llamada al constructor.
código crapcode olor
Las dudas vagas que tiene sobre el código se denominan técnicamente "olor de código", lo que significa que parece sospechoso por alguna razón: la longitud "se siente" larga para lo que está haciendo, en este caso. Puede que haya algo mal, tal vez no; un "olor a código" requiere un escrutinio más detenido para determinar si algo está mal.
Un olor a código que veo son los múltiples whilebucles de aspecto similar , cada uno buscando diferentes caracteres requeridos. No quiero escribir código difícil de entender por tener menos líneas. "Menos líneas de código" por sí solo no es una razón para cambiar las cosas. Aquí hay una idea, tal vez sea una mejora o tal vez no:
Dígale al usuario los caracteres requeridos por adelantado cuando se le solicite la contraseña.
Una cadena es iterable, puede "forEach". A Stringes de hecho una matriz de Char, técnicamente.
forEach (char character in enteredPassword) { ... }
Examine cada carácter por su tipo. Mantenga una cuenta separada para cada tipo de carácter.
Después de la forEachprueba, cada contador para el mínimo requerido. Si symbolses cero, por ejemplo, agregue "se requiere al menos un carácter de símbolo" a un mensaje de error.
FYI
Hay un viejo dicho con un núcleo de verdad: si resuelves un problema con una expresión regular, ahora tienes dos problemas
¿La línea 221 es demasiado para esto?
Hay muchas pautas, principios, "ismos", etc. para evaluar la calidad del código. El recuento de líneas no es uno de ellos.