Manipulando Strings com Segurança

Bruno Silveira Cruz (e-mail) é Analista de Sistemas, instrutor certificado Microsoft, mais de 2 anos de experiencia lecionando cursos oficiais. Possui 6 anos de experiência em infra-estrutura, e 4 em desenvolvimento, 2 com a pltaforma .NET e C#. Certficado MCP, MCSA 2000 e 2003, MCSA Exchange 2000, MCSE 2000, MCAD C# e MCT, mais de 15 exames de certificação no currículo.

O .NET Framework 2.0 introduziu uma nova e muito útil classe para trabalharmos com strings de maneira segura. A classe SecureString oferece um objeto pré-definido de fácil uso, que podemos usar para guardar informações confidenciais como senhas, número de cartões de credito, e quaisquer outros dados confidenciais.

String x SecureString

Se você trabalha com o Framework, já deve conhecer o objeto String. Na verdade quando referenciamos a classe System.String usamos tradicionalmente o alias, string. O objeto string é uma coleção de objetos System.Char (char) agrupados. Cada char refere-se ao valor numérico do caractere em questão, na tabela Unicode. Cada caractere é codificado usando UTF-16.

Uma string é também um objeto imutável. Imutável porque após sua criação, não pode ser modificada.

string s = "System.String test";

s.ToUpper();

Console.WriteLine(s); //---> System.String test

Console.WriteLine(s.ToUpper()); //---> SYSTEM.STRING TEST

s = "Nova String";

Console.WriteLine(s); //---> Nova String

Quantas instâncias de string temos nesse código? Se você respondeu 4, acertou. A primeira é criada na declaração da variável s na primeira linha. Ao chamarmos o método ToUpper() temos retornada uma segunda instância. A terceira instância está na quarta linha, Console.WriteLine(s.ToUpper()). Na quinta linha está a quarta instância, quando eu atribuo um novo valor ao objeto string s, criado anteriormente.

Na verdade, quando atribuo um novo valor a um objeto string, na tentativa de substituir o valor anterior, a CLR cria uma nova instância do objeto string e descarta a anterior. O problema é que, eu não posso descartar imediatamente um objeto string, ou ainda predizer quando esse objeto será descartado, mesmo que meu aplicativo não o utilize mais.

Aí começam as implicações na segurança do aplicativo. Se você usou um objeto string para guardar ou manipular uma senha, por exemplo, esse objeto, em algum momento, irá residir em uma area da mémoria, e poderá ser recuperado, mesmo que seu aplicativo já o tenha descartado.

SecureString

O classe SecureString criar objetos similares a classe System.String, mas que são mutáveis e são encriptados automaticamente, no momento de sua criação. No entanto, a classe SecureString não possui metodos para manipulação da string. Para recuperar o texto de uma classe SecureString voce deverá usar

System.Runtime.InteropServices.Marshal.SecureStringToBSTR.

// Checa se o objeto SecureString é Read-Only

if (password.IsReadOnly())

{

// Se for Read-Only, descarta a instância atual...

password.Dispose();

// ... e cria um novo objeto SecureString.

password = new SecureString();

}

// Recupera o valor da TextBox

if ((PasswordTextBox.Text != String.Empty))

{

if (((e.KeyCode != Keys.Back) && (e.KeyCode != Keys.Delete)))

{

// Recupera o ultimo char. Essa implementação tem a limitação de velocidade. Se o usuario digitar a senha muito rapido

// o texto recuperado do TextBox não equivalera ao digitado.

char ch = PasswordTextBox.Text.ToCharArray()[PasswordTextBox.Text.Length - 1];

password.AppendChar(ch);

}

}

Recuperando o Texto

//O objeto bstr do tipo IntPtr terá a cópia decriptada do texto do objeto SecureString.

IntPtr bstr =Marshal.SecureStringToBSTR(password);

try

{

//Recupera uma string do objeto SecureString. Desta maneira já temos uma copia decriptada do texto do SecureString na mémoria.

PasswordVerifyLabel.Text = Marshal.PtrToStringBSTR(bstr);

}

finally

{

//Zera a memoria do objeto bstr, apagando a cópia decriptada do objeto SecureString.

Marshal.ZeroFreeBSTR(bstr);

}

Em nosso código de produção, devemos contar com uma rotina para interpretar as teclas Delete e Backspace e manipular o objeto SecureString corretamente. Nosso exemplo tem mais uma limitação: Se o usuário digitar a senha muito rápido, o objeto SecureString não será preenchido corretamente. Isso acontece porque estamos nos baseando no texto digitado no controle. Em um aplicativo de produção devemos monitorar os eventos KeyDown, KeyUp e TextChanged, e converter cada char digitado para o símbolo especifico.

Dúvidas, criticas ou sugestões? Mande para o meu e-mail.

Será um prazer ter sua opinião. Até a próxima!