It Devel Geração randômica de senha com C#
Post
Cancel

Geração randômica de senha com C#

Neste post será criado um código em C# para geração de senha randômica e cumprindo os níveis de complexidade estabelecidos.

No Windows geralmente o nível de complexidade exigido é:

  • Não conter partes significativas do nome da conta do usuário ou o nome todo
  • Ter pelo menos seis caracteres de comprimento
  • Conter caracteres de três das quatro categorias a seguir:
    • Caracteres maiúsculos do inglês (A-Z)
    • Caracteres minúsculos do inglês (a-z)
    • 10 dígitos básicos (0-9)
    • Caracteres não-alfabéticos (por exemplo, !, $, #, %)

Desta forma criei um código para cumprir todos estes requisitos.

A base de geração de alguns dados foi a tabela ASCII (conforma imagem abaixo). Da tabela foram utilizados os caracteres A-Z, a-z, 0-9 e alguns caracteres especiais. Porém no código eles aparecem como os seus decimais.

Tabela ASCII

Como referência temos os itens:

[sourcecode language="csharp"]
using System;
using System.Collections.Generic;
using System.Text;
[/sourcecode]

A Classe é:

[sourcecode language="csharp"]

public class PasswordGenerator
{
//Caracteres especiais utilizados
private String[] Special = new String[] { "@", "#", "$", "!", "%", "-", "_" };

//Requisitos mínimos de senha
private Boolean useLowerCase;
private Boolean useUpperCase;
private Boolean useDigits;
private Boolean useSpecial;

public Boolean UseLowerCase { get { return useLowerCase; } set { useLowerCase = value; } }
public Boolean UseUpperCase { get { return useUpperCase; } set { useUpperCase = value; } }
public Boolean UseDigits { get { return useDigits; } set { useDigits = value; } }
public Boolean UseSpecial { get { return useSpecial; } set { useSpecial = value; } }

public PasswordGenerator() : this(true, true, true, true) { }

public PasswordGenerator(Boolean UseLowerCase, Boolean UseUpperCase, Boolean UseDigits, Boolean UseSpecial)
{
this.useLowerCase = UseLowerCase;
this.useUpperCase = UseUpperCase;
this.useDigits = UseDigits;
this.useSpecial = UseSpecial;

if ((!this.useLowerCase) && (!this.useUpperCase) && (!this.useDigits) && (!this.useSpecial))
this.useLowerCase = true;

}

public String Generate(Int32 Length)
{
String passwd = "";

Int32 uppper = 0;
Int32 lower = 0;
Int32 digits = 0;
Int32 special = 0;

Random rnd = new Random();

while(passwd.Length < Length)
{
Int32 i = rnd.Next(1, 4);
Int32 i2 = 0;

//Regras de checagem de requisitos
while (i != i2)
{
switch (i)
{
case 1:
if (!useDigits){
i++;
break;
}
else if (digits > 0)
{
if ((useUpperCase) && (uppper == 0))
i = i2 = 2;
else if ((useLowerCase) && (lower == 0))
i = i2 = 3;
else if ((useSpecial) && (special == 0))
i = i2 = 4;
else
i2 = i;
}
else
{
i2 = i;
}
break;

case 2:
if (!useUpperCase)
{
i++;
break;
}
else if (uppper > 0)
{
if ((useDigits) && (digits == 0))
i = i2 = 1;
else if ((useLowerCase) && (lower == 0))
i = i2 = 3;
else if ((useSpecial) && (special == 0))
i = i2 = 4;
else
i2 = i;
}
else
{
i2 = i;
}
break;

case 3:
if (!useLowerCase)
{
i++;
break;
}
else if (lower > 0)
{
if ((useDigits) && (digits == 0))
i = i2 = 1;
else if ((useUpperCase) && (uppper == 0))
i = i2 = 2;
else if ((useSpecial) && (special == 0))
i = i2 = 4;
else
i2 = i;
}
else
{
i2 = i;
}
break;

case 4:
if (!useSpecial)
{
i++;
break;
}
else if (special > 0)
{
if ((useDigits) && (digits == 0))
i = i2 = 1;
else if ((useUpperCase) && (uppper == 0))
i = i2 = 2;
else if ((useLowerCase) && (lower == 0))
i = i2 = 3;
else
i2 = i;
}
else
{
i2 = i;
}
break;
}
}

String newItem = "";
switch (i2)
{
case 1:
newItem = ((char)(rnd.Next(48, 57))).ToString();
digits++;
break;

case 2:
newItem = ((char)(rnd.Next(65, 90))).ToString();
uppper++;
break;

case 3:
newItem = ((char)(rnd.Next(97, 122))).ToString();
lower++;
break;

case 4:
newItem = Special[rnd.Next(0, Special.Length - 1)];
special++;
break;
}

//Randomiza a posição dos caracteres
if (passwd.Length > 0)
{
System.Threading.Thread.Sleep(1);
Int32 pos = rnd.Next(0, passwd.Length - 1);
passwd = passwd.Insert(pos, newItem);
}
else
{
passwd = newItem;
}

//Slep necessário para que o 'rnd.Next' traga valores diferentes
System.Threading.Thread.Sleep(5);
}

return passwd;
}
}
[/sourcecode]

Para a utilização da classe temos este exemplo com um loop gerando 10 senhas diferentes com 16 caracteres cada.

[sourcecode language="csharp"]
PasswordGenerator gen = new PasswordGenerator();

for (Int32 i = 0; i < 10; i++)
{
Console.WriteLine(gen.Generate(16));
}
[/sourcecode]

Segue abaixo o aplicativo completo para download

Geração de Senha