segunda-feira, agosto 28, 2006

System.Security.SecureString


Como post inicial, vou falar sobre uma nova classe introduzida no .Net Framework 2.0 a SecureString, localizada no namespace System.Security.


A SecureString foi desenvolvida para auxiliar os desenvolvedores proteger informações sensíveis enquanto estão em memória.


Abaixo seguem algumas vantagens da SecureString com relação ao System.String:



  • É possivel ser removida da memória, quando não for mais necessária, utilizando o método Dispose.

  • O valor contido na SecureString é encriptado quando a instancia é inicializada.

  • Não possui membros para inspecionar, comparar ou converter o valor da instancia.

  • É protegida em memória utilizando a DAPI.



Para ilustrar a utilização da SecureString, criei uma classe chama SecureStringHelper,
que encapsula o processo de adicionar e obter valores de uma instância da classe SecureString.



using System;
using System.Collections.Generic;
using System.Text;

using System.Security;
using System.Runtime.InteropServices;

namespace SecureStringPost
{
/// Classe auxiliar que encapsula a utilização da classe SecureString.
/// Esta classe precisa ser compilada com a opção /unsafe.
/// Por utilizar código não seguro.
public class SecureStringHelper : IDisposable
{
private SecureString _secureString;

/// Cria uma nova instancia da classe SecureStringHelper
public SecureStringHelper(byte[] buffer)
{
this.MakeSecure(buffer);
}

/// Protege o buffer passado como parametro
private unsafe void MakeSecure(byte[] buffer)
{
// Obtem o tamanho em chars do buffer.
int size = Encoding.Default.GetCharCount(buffer);
// Aloca memória na stack, utilizando método stackalloc,
// com o tamanho do buffer.
// Memória alocada utilizando stackalloc fica em memória
// até o método retornar.
char* tempChar = stackalloc char[size];

// Faz um 'pin' do buffer
fixed (byte* p = buffer)
{
// Obtem um ponteiro para um Char*.
Encoding.Default.GetChars(p, buffer.Length, tempChar, size);
// Inicializa a classe secure string, passando o Char* e seu tamanho.
_secureString = new SecureString(tempChar, size);
// Protege a secure string contra modificações.
_secureString.MakeReadOnly();
}
buffer = null;
tempChar = null;
return;
}

/// Obtem o valor contido na instancia da secure string.
///
/// Retorna uma instancia da System.String contendo o valor
/// protegido pela System.Security.SecureString.
public string GetStringUnsecure()
{
IntPtr ptr = IntPtr.Zero;
string insecure = null;

try
{
// Obtem um ponteiro para um BSTR, onde irá conter
// o valor desprotegido, que está na na System.Security.SecureString
ptr = Marshal.SecureStringToBSTR(_secureString);
// Converte o ponteiro obtido para uma instancia System.String.
insecure = Marshal.PtrToStringAuto(ptr);
}
finally
{
// Libera o ponteiro alocado.
Marshal.FreeBSTR(ptr);
}

// retorna uma instancia não segura da string.
return insecure;
}

/// Libera a memória alocada pela SecureStringHelper.
public void Dispose()
{
if (_secureString != null)
_secureString.Dispose();
}
}
}

/// Exemplo de como utilizar a classe acima.
class Program
{
static void Main(string[] args)
{
string unsecureString = "MINHA STRING NÃO SEGURA";
byte[] unsecureBuffer = Encoding.Default.GetBytes(unsecureString);

using (SecureStringHelper helper = new SecureStringHelper(unsecureBuffer))
{
Console.WriteLine(helper.GetStringUnsecure());
}

Console.ReadLine();
}
}


Bom, espero que tenham gostado do primeiro post.


Até mais!
Valeu!