Como usar DPAPI com IsolatedStorage na versão Mango do Windows Phone 7

Artigo original publicado em 3 de julho de 2011, domingo

Estava trabalhando na versão Mango do Windows Phone 7 outro dia. Um dos ótimos recursos (há muitos) que foi adicionado é suporte a DPAPI. Um dos casos em que você pode desejar usar isso é para criptografar alguns conteúdos antes de armazená-los localmente. No WP7, quando um aplicativo armazena dados localmente, ele usa algo denominado IsolatedStorage. O sistema IsolatedStorage tem algumas classes agradáveis para ajudar seus aplicativos a ler e gravar nele. Algo que descobri com isso (pelo menos neste ponto) é que ele basicamente não funciona bem com conteúdo criptografado por DPAPI. Deixe-me explicar o que quero dizer com isso.

Suponha que você use a DPAPI para criptografar alguns conteúdos e gravá-los em disco. Agora você deseja ler os dados criptografados de volta, descriptografá-los e fazer algo com eles. Bem, se você seguir a maioria dos exemplos de IsolatedStorage, fará algo como:

//get into isolated storage for the credentials
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
 //stream in our registration file
 using (var stream = new
  IsolatedStorageFileStream(REG_INFO_FILE, FileMode.Open, FileAccess.Read, store))
 {
  //read the contents into a variable
  using (var reader = new StreamReader(stream))
  {
   //create and fill the byte array with the raw data so you can use it
   byte[] rawData = new byte[reader.Length];
   reader.Read(rawData, 0, Convert.ToInt16(byteStream.Length));

   //now decrypt it
   byte[] safeData = ProtectedData.Unprotect(rawData, null);
  }
 }
}

O problema é que ao chamar Unprotect, você obterá um erro com as linhas de preenchimento sendo adicionadas. O problema são alguns caracteres extras que o leitor padrão de IsolatedStorageFileStream adiciona quando ele lê o conteúdo para você. Para solucionar esse problema, você precisa obter uma referência ao fluxo subjacente e ler diretamente dele. Por exemplo, este código:

//create and fill the byte array with the raw data so you can use it
byte[] rawData = new byte[reader.Length];
reader.Read(rawData, 0, Convert.ToInt16(byteStream.Length));

Deve ser alterado para este:

Stream byteStream = reader.BaseStream;                               

//create and fill the byte array with the raw data so you can use it
byte[] rawData = new byte[byteStream.Length];
byteStream.Read(rawData, 0, Convert.ToInt16(byteStream.Length));

//now decrypt it
byte[] safeData = ProtectedData.Unprotect(rawData, null);

Assim que você começar a usar o BaseStream, isso deve resolver todos os erros de preenchimento.

 

Esta é uma postagem de blog traduzida. Consulte o artigo original em Using DPAPI with IsolatedStorage In Windows Phone 7 Mango Release