Compartilhar via


Este artigo foi traduzido por máquina.

Informativos sobre segurança

Agilidade de criptografia

Bryan Sullivan

Conteúdo

Planejamento de futuros maliciosos
Problemas potenciais
Alternativa de uso e sintaxe
Outro benefício de agilidade de criptografia
Resumindo

Em todo o histórico, as pessoas usaram várias formas de codificações para ocultar informações de seus adversaries. Julius Caesar usado uma codificação de mudança de local de três (a letra A é convertida em D, B é convertida em E e assim por diante) para se comunicar planos de batalha. Durante a guerra mundial, marinho alemão usado um sistema significativamente mais avançado — a máquina enigma — para criptografar mensagens enviadas para seus barcos U. Hoje em dia, usamos ainda mais sofisticados mecanismos de criptografia como parte da infra-a estrutura de chave pública que ajuda a realizar transações seguras na Internet.

Mas para desde cryptographers ter sido fazer códigos secretos, cryptanalysts ter sido tentando quebrá-los e roubar informações e, às vezes, o código separadores bem-sucedida. Algoritmos de criptografia considerados seguros uma vez são desfeitos e processados inútil. Às vezes sutis falhas estão localizadas nos algoritmos e às vezes, é simplesmente uma questão de invasores ter acesso a mais potência de computação para executar ataques de força bruta.

Recentemente, pesquisadores de segurança demonstraram pontos fracos do algoritmo de hash MD5 como resultado de colisões; ou seja, eles mostraram que duas mensagens podem ter o mesmo valor de hash MD5 calculado. Ele criou um ataque de prova de conceito contra esta vulnerabilidade direcionado a infra-as públicas chaves estruturas que proteger transações de comércio eletrônico na Web. Adquirindo um certificado de site especialmente criado de uma autoridade de certificação (CA) que usa MD5 para assinar seus certificados, os pesquisadores foram capazes de criar um certificado de autoridade de certificação não autorizado que poderia ser efetivamente usado para representar potencialmente qualquer site na Internet. Eles concluída que MD5 não é apropriado para assinar certificados digitais e que uma alternativa mais forte, tal como um dos algoritmos SHA-2, deve ser usada. (Se você estiver interessado em aprender mais sobre esta pesquisa, você pode ler awhite paper.)

Essas descobertas são certamente causar para preocupação, mas não são uma grande surpresa. Pontos fracos MD5 teóricas tem foi demonstrados por anos, e o uso de MD5 em produtos da Microsoft tem sido proibido pelos padrões de criptografia SDL da Microsoft desde 2005. Outros algoritmos populares de uma vez, como o SHA-1 e RC2, tem sido proibidos da mesma forma. a Figura 1 mostra uma lista completa dos algoritmos criptográficos proibido ou aprovados pelo SDL. A lista de algoritmos aprovados pelo SDL está atual como da redação deste artigo, mas essa lista é revisada e atualizada anualmente como parte do processo de atualização do SDL.

A Figura 1 aprovada SDL algoritmos de criptografia
Tipo de algoritmo Proibido (algoritmos sejam substituídos no código existente ou usadas somente para descriptografia) Aceitável (algoritmos aceitáveis para código existente, exceto os dados confidenciais) Recomendado (algoritmos para o novo código)
Bloquear simétrica DES, DESX, RC2, SKIPJACK 3DES (chave 2 ou 3) AES (> = 128 bits)
Fluxo simétrico LACRE, CYLINK_MEK, RC4 (< 128 bits) RC4 (> = 128 bits) Nenhum, codificação de bloco é preferencial
Assimétrica RSA (< 2048 bits), Diffie-Hellman (< 2048 bits) RSA (> = 2048bit), Diffie-Hellman (> = 2048bit) RSA (> = 2048bit), Diffie-Hellman (> = 2048bit), ECC (> = 256 bits)
Hash (inclui o uso HMAC) SHA-0 (SHA), SHA-1, MD2, MD4, MD5 SHA-2 SHA-2 (inclui: SHA-256, SHA-384 e SHA-512)
HMAC chave lengths <112 bits >= 112 bits >= 128 bits

Mesmo se você seguir essas normas em seu próprio código, não usando apenas os algoritmos mais seguros e comprimentos de chave mais longo, há nenhuma garantia de que o código que você escreve hoje permanecerá seguro. Na verdade, ele provavelmente não permanecerá seguro se o histórico é qualquer guia.

Planejamento de futuros maliciosos

Você pode solucionar esse cenário desagradável codificam por indo por meio dos seus aplicativos antigos bases de código, separação saída instanciações de algoritmos vulneráveis, substituí-los com novos algoritmos, recriar os aplicativos, executá-los por meio de testes de regressão e emissão, em seguida, patches ou service packs para os usuários. Isso não é apenas um muito trabalho para você, mas deixa ainda os usuários em risco até que você pode obter as correções fornecidas.

Uma alternativa melhor é planejar para esse cenário desde o início. Em vez de embutir em código específicos algoritmos criptográficos em seu código, use um dos recursos de criptografia agilidade internos do Microsoft .NET Framework. Vamos dar uma olhada em alguns trechos de código translation from VPE for Csharp, começando com o exemplo menos ágil:

private static byte[] computeHash(byte[] buffer)
{
   using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
   {
      return md5.ComputeHash(buffer);
   }
}

Esse código é completamente nonagile. Ele está vinculado a um algoritmo específico (MD5), bem como uma implementação específica desse algoritmo, a classe MD5CryptoServiceProvider. Modificar este aplicativo para usar um algoritmo de hash seguro precisaria alterar código e emitir um patch. Eis um exemplo melhor pouco:

private static byte[] computeHash(byte[] buffer)
{
   string md5Impl = ConfigurationManager.AppSettings["md5Impl"];
   if (md5Impl == null)
      md5Impl = String.Empty;

   using (MD5 md5 = MD5.Create(md5Impl))
   {
      return md5.ComputeHash(buffer);
   }
}

Essa função usa a classe System.Configuration.Configuration Gerenciador para recuperar uma configuração de aplicativo personalizado (a configuração "md5Impl") do arquivo de configuração do aplicativo. Nesse caso, a configuração é usada para armazenar o nome forte da classe de implementação de algoritmo que deseja usar. O código passa o valor recuperado dessa configuração para a função estática MD5.Create para criar uma instância da classe desejada. (System.Security.Cryptography.MD5 é uma classe base abstrata da quais todas as implementações do MD5 algoritmo deve derivar.) Por exemplo, se a configuração de aplicativo para md5Impl foi definida para a seqüência de caracteres "System.Security.Cryptography.MD5Cng, System.Core, versão = 3.5.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089", MD5.Create seria criar uma instância da classe MD5Cng.

Essa abordagem resolve apenas metade do nosso problema de agilidade de criptografia, por isso realmente não é nenhuma solução em todos os. Agora podemos especificar uma implementação do algoritmo MD5 sem ter que alterar qualquer código de origem, que pode ser útil se uma falha for descoberta em uma implementação específica, como MD5Cng, mas ainda estão vinculados ao uso de MD5 em geral. Para resolver esse problema, podemos manter abstração para cima:

private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create("MD5"))
   {
      return hash.ComputeHash(buffer);
   }
}

A princípio, este trecho de código não procura substancialmente diferente do primeiro exemplo. Parece que nós já novamente embutida o algoritmo MD5 no aplicativo por meio da chamada para HashAlgorithm.Create("MD5"). Surpreendentemente Contudo, esse código é substancialmente mais criptograficamente ágil que os dois outros exemplos. Enquanto o comportamento padrão do método chamar HashAlgorithm.Create ("MD5") — como do .NET 3.5 — é criar uma instância da classe MD5CryptoServiceProvider, o comportamento de runtime pode ser personalizado por fazer uma alteração no arquivo machine.config.

Vamos alterar o comportamento desse código para criar uma instância de SHA512algorithm em vez de MD5. Para fazer isso, precisamos adicionar dois elementos para o arquivo machine.config: um elemento <cryptoclass> para mapear um algoritmo amigável nome para a classe de implementação do algoritmo deseja; e um elemento <nameentry> para mapear nome amigável do antigo, substituído algoritmo para o novo nome amigável.

<configuration>
  <mscorlib>
    <cryptographySettings>
      <cryptoNameMapping>
        <cryptoClasses>
          <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
            Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
        </cryptoClasses>
        <nameEntry name="MD5" class="MyPreferredHash"/>
      </cryptoNameMapping>
    </cryptographySettings>
  </mscorlib>
</configuration>

Agora, quando o nosso código faz sua chamada HashAlgorithm.Create("MD5"), o CLR examina o arquivo machine.config e vê que a seqüência de caracteres "MD5" deve mapear para o nome do algoritmo amigável "MyPreferredHash". Em seguida, ele vê que "MyPreferredHash" mapeia para a classe SHA512CryptoServiceProvider (conforme definido no assembly System.Core, com a versão especificada, cultura e token de chave pública) e cria uma instância dessa classe.

É importante observar que o algoritmo remapeamento ocorre não em tempo de compilação, mas em tempo de execução: é machine.config do usuário que controla o remapeamento, não do desenvolvedor. Como resultado, essa técnica resolve nossa dilema do que está sendo vinculada a um determinado algoritmo que pode estar desfeito em algum momento no futuro. Evitando embutir em código da classe de algoritmo de criptografia para o aplicativo — codificação apenas o tipo abstrato do algoritmo de criptografia, HashAlgorithm, em vez disso — criamos um aplicativo no qual o usuário final (mais especificamente, alguém com direitos administrativos para editar o arquivo machine.config no computador onde o aplicativo está instalado) pode determinar exatamente qual algoritmo e a implementação o aplicativo utilizará. Um administrador pode optar por substituir um algoritmo que recentemente foi quebrado com um ainda considerado seguro (por exemplo, substitua MD5 SHA-256) ou para substituir um algoritmo seguro pró-ativamente com uma alternativa com um comprimento de bit (substituir SHA-256 com SHA-512) mais.

Problemas potenciais

Modificar o arquivo machine.config para remapear as seqüências de tipo de algoritmo padrão (como "MD5" e "SHA1") pode resolver problemas de agilidade de criptografia, mas ele pode criar problemas de compatibilidade ao mesmo tempo. Fazer alterações em machine.config afeta todos os aplicativos .NET na máquina. Outros aplicativos instalados no computador podem depender MD5 especificamente e alterar os algoritmos usados por esses aplicativos pode rompê-los de maneiras inesperadas que são difíceis de diagnosticar. Como alternativa para forçando alterações amplas para todo o computador, é melhor usar nomes amigáveis personalizados, específicas do aplicativo em seu código e mapear essas entradas de nome para classes preferenciais no machine.config. Por exemplo, pode alterar "MD5" para "MyApplicationHash" em nosso exemplo:

private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create("MyApplicationHash"))
   {
      return hash.ComputeHash(buffer);
   }
}

Em seguida, podemos adicionar uma entrada ao arquivo machine.config para mapear "MyApplicationHash" para a classe "MyPreferredHash":

<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, 
     System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>

Você também pode mapear vários nomes amigáveis para a mesma classe; por exemplo, você pode ter um nome amigável para cada um dos aplicativos e assim alterar o comportamento de aplicativos específicos sem afetar todos os outros aplicativos no computador:

<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, 
     System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
<nameEntry name="MyApplication2Hash" class="MyPreferredHash"/>
<nameEntry name="MyApplication3Hash" class="MyPreferredHash"/>

No entanto, ainda não estamos fora da floresta com relação aos problemas de compatibilidade em nossos próprios aplicativos. Você precisa planejar com antecedência em relação ao tamanho do armazenamento, para as variáveis locais (armazenamento temporário) e banco de dados e esquemas XML (armazenamento persistente). Por exemplo, MD5 hashes são sempre 128 bits de comprimento. Se orçamento exatamente de 128 bits em seu código ou o esquema para armazenar a saída de hash, você não poderá atualizar para o SHA-256 (saída de comprimento de bit 256) ou SHA-512 (saída de comprimento de bit 512).

Isso beg a questão de quanto de armazenamento é suficiente. É 512 bits suficiente, ou você deverá usar 1.024, 2.048 ou mais? Não é possível forneço uma regra rígida aqui porque cada aplicativo tem requisitos diferentes, mas como uma regra prática é recomendável que você orçamento duas vezes como muito espaço para hashes como você usa no momento. Para simétrica e assimétrica-dados criptografados, você pode reservar um extra 10 % do espaço no máximo. É improvável que os novos algoritmos com tamanhos de saída significativamente maiores do que algoritmos existentes serão aceitas amplamente.

No entanto, os aplicativos que armazenam valores de hash ou dados criptografados em um estado persistente (por exemplo, em um arquivo ou banco de dados) têm problemas maiores que reservar espaço suficiente. Se você manter dados usando um algoritmo e tente operar em que os dados mais tarde usando um algoritmo diferente, você não obterá os resultados esperados. Por exemplo, é uma boa idéia para armazenar hashes de senhas em vez das versões de texto sem formatação completa. Quando o usuário tenta fazer logon, o código pode comparar o hash da senha fornecida pelo usuário para o hash armazenado no banco de dados. Se os hashes corresponderem, o usuário é autêntico. No entanto, se um hash está armazenado em um formato (digamos, MD5) e um aplicativo é atualizado para usar outro algoritmo (digamos, SHA-256), os usuários nunca poderão fazer logon porque o valor de hash SHA-256 das senhas sempre serão diferente o valor de hash MD5 dessas mesmas senhas.

Você pode obter solução alternativa para esse problema em alguns casos, armazenando o algoritmo original como metadados juntamente com os dados reais. Em seguida, quando operar em dados armazenados, use os métodos de agilidade (ou reflexão) para instanciar o algoritmo usado originalmente em vez do algoritmo atual:

private static bool checkPassword(string password, byte[] storedHash,
   string storedHashAlgorithm)
{
   using (HashAlgorithm hash = HashAlgorithm.Create(storedHashAlgorithm))
   {
      byte[] newHash = 
         hash.ComputeHash(System.Text.Encoding.Default.GetBytes(password));
      if (newHash.Length != storedHash.Length)
         return false;
      for (int i = 0; i < newHash.Length; i++)
         if (newHash[i] != storedHash[i])
            return false;
      return true;
   }
}

Infelizmente, se você precisar comparar dois hashes armazenados, eles precisam ter sido criado usando o mesmo algoritmo. Não é simplesmente nenhuma maneira para comparar um hash MD5 para um hash de SHA-256 e determinar se eles foram ambas criados a partir dos mesmos dados originais. Não há uma boa solução de agilidade de criptografia para esse problema e o melhor conselho que pode oferecer é que você deve escolher o algoritmo mais seguro disponível no momento e, em seguida, desenvolver um plano de atualização no caso desse algoritmo é interrompido posteriormente. Em geral, agilidade criptografia tende a funcionar muito melhor para dados transitórios que dados persistentes.

Alternativa de uso e sintaxe

Supondo que o design de aplicativo permite o uso de criptografia agilidade, vamos continuar a observar alguns usos alternativos e sintaxes para essa técnica. Nós já enfoca quase inteiramente algoritmos de hash a esse ponto no artigo, mas agilidade criptografia também funciona para outros tipos de algoritmo de criptografia. Basta chamar o método criar estático da classe base abstrata apropriado: SymmetricAlgorithm para algoritmos de criptografia simétrica de (chave secreta) como AES; AsymmetricAlgorithm para assimétrica (chave pública) algoritmos de criptografia, como RSA; KeyedHashAlgorithm para hashes com chave; e HMAC para códigos de autenticação de mensagem baseado em hash.

Você também pode usar criptografia agilidade para substituir uma das classes padrão do algoritmo de criptografia .NET por uma classe de algoritmo personalizado, como um dos algoritmos desenvolvido pela equipe de segurança do CLR e carregado no CodePlex. No entanto, altamente é desencorajado escrever suas próprias bibliotecas de criptografia personalizadas. Seu algoritmo tortilhas consiste em um ROT13 seguido por um bit a bit shift esquerda e um XOR com nome do seu gato pode parecer seguro, mas ele será representar pouco desafio para um separador de especialista em código. A menos que você seja um especialista em criptografia, deixe o algoritmo de design para os profissionais.

Também resistir à tentação de desenvolver seus próprios algoritmos — ou a reviver longa fila de inatividade, oculte as, como a codificação Vigenère — até mesmo em situações onde você não precisa criptograficamente forte proteção. O problema não é tão bem que faria com sua codificação, mas que os desenvolvedores que vêm após irá fazer com ele. Um novo desenvolvedor que localiza sua classe de algoritmo personalizado no código base anos mais tarde pode decidir que é o que ele precisa para a ativação de produto nova lógica de geração de chave.

Até agora que vimos uma das sintaxes para implementação de código criptograficamente ágil, AlgorithmType.Create(algorithmName), mas duas outras abordagens são criadas no .NET Framework. A primeira é usar a classe System.Security.Cryptography.CryptoConfig:

private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = (HashAlgorithm)CryptoConfig.CreateFromName("MyApplicationHash"))
   {
      return hash.ComputeHash(buffer);
   }
}

Esse código executa as mesmas operações como nosso exemplo anterior usando HashAlgorithm.Create("MyApplicationHash"): o CLR examina o arquivo machine.config para um remapeamento da seqüência de caracteres "MyApplicationHash" e usa a classe algoritmo remapeados se ele encontrar um. Observe que temos que converter o resultado de CryptoConfig.CreateFromName porque possui um tipo de retorno de System.Object e pode ser usado para criar SymmetricAlgorithms, AsymmetricAlgorithms ou qualquer outro tipo de objeto.

A sintaxe alternativa segunda é chamar o método Create algoritmo estático em nosso exemplo original mas sem parâmetros, como este:

private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create())
   {
      return hash.ComputeHash(buffer);
   }
}

Nesse código, simplesmente pedimos a estrutura para fornecer uma instância de qualquer o implementação de padrão de algoritmo de hash é. Você encontrará a lista de padrões para cada uma das classes base System.Security.Cryptography abstratas (como do .NET 3.5) na Figura 2 .

Figura 2 padrão algoritmos e implementações no .NET Framework 3.5
Classe base abstrata Algoritmo de padrão Implementação do padrão
HashAlgorithm SHA-1 SHA1CryptoServiceProvider
SymmetricAlgorithm AES (Rijndael) RijndaelManaged
AsymmetricAlgorithm RSA RSACryptoServiceProvider
KeyedHashAlgorithm SHA-1 HMACSHA1
HMAC SHA-1 HMACSHA1

Para HashAlgorithm, você pode ver que o algoritmo padrão é SHA-1 e a classe de implementação do padrão é SHA1CryptoServiceProvider. No entanto, nós sabemos que SHA-1 é proibido pelos padrões de criptografia do SDL. Para o momento, vamos ignorar o fato de que a possíveis problemas de compatibilidade tornam geralmente imprudente remapear algoritmo inerente nomes como "SHA1" e alterar nosso machine.config para remapear "SHA1" para SHA512CryptoServiceProvider:

<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="SHA1" class="MyPreferredHash"/>

Agora vamos inserir uma linha de depuração na função computeHash para confirmar que o algoritmo foi remapeado corretamente e, em seguida, executar o aplicativo:

private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create())
   {
      Debug.WriteLine(hash.GetType());
      return hash.ComputeHash(buffer);
   }
}

A saída de depuração desse método é:

System.Security.Cryptography.SHA1CryptoServiceProvider

O que aconteceu? Nós não remapear SHA1 para SHA-512? Na verdade, não, nós não. Nós remapeados somente a seqüência "SHA1" para a classe SHA512CryptoServiceProvider e nós não passou a seqüência de caracteres "SHA1" como um parâmetro para a chamada para HashAlgorithm.Create.

Mesmo que criar parece não ter nenhum parâmetro de seqüência de caracteres para remapear, é possível alterar o tipo de objeto é criado. Você pode fazer isso porque HashAlgorithm.Create() é apenas atalho sintaxe para HashAlgorithm.Create("System.Security.Cryptography.HashAlgorithm"). Agora vamos adicionar outra linha ao arquivo machine.config para remapear "System.Security.Cryptography.HashAlgorithm" para SHA512CryptoServiceProvider e, em seguida, executar o aplicativo novamente:

<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
     Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="SHA1" class="MyPreferredHash"/>
<nameEntry name="System.Security.Cryptography.HashAlgorithm" class="MyPreferredHash"/>

A saída de depuração do computeHash agora é exatamente o que esperávamos:

System.Security.Cryptography.SHA512CryptoServiceProvider

No entanto, lembre-se de que remapeamento classes dessa maneira pode criar problemas de compatibilidade inesperado e difícil de depuração. É preferível usar nomes amigáveis de específicas do aplicativo que podem ser remapeados com menos chance de causar problemas.

Outro benefício de agilidade de criptografia

Em adição aos permitindo que você substitua algoritmos interrompidos imediatamente sem ter que recompilar, agilidade criptografia pode ser usada para melhorar o desempenho. Se você já tiver estava no espaço para nome System.Security.Cryptography, você talvez tenha percebido que freqüentemente várias classes de implementação diferentes existem para um determinado algoritmo. Por exemplo, há três implementações diferentes de SHA-512: SHA512Cng, SHA512CryptoServiceProvider e SHA512Managed.

Uma dessas classes, SHA512Cng geralmente oferece o melhor desempenho. Um teste rápido em meu laptop (em execução Windows 7 versão RC) mostra que as classes –Cng em geral são cerca de 10 % mais rápido do que-CryptoServiceProvider e - Managed classes. Meus colegas no grupo principal arquitetura informar-me que, na verdade, pode executar 10 vezes mais rápido do que as outras em algumas circunstâncias classes –Cng!

Claramente, usando as classes –Cng é preferível e pode configurar o nosso arquivo machine.config para remapear implementações de algoritmo para usar essas classes, mas a opção-Cng classes não estão disponíveis em cada sistema operacional. Somente Windows Vista, Windows Server 2008 e Windows 7 (e versões posteriores, presumivelmente) oferece suporte a –Cng. Tentar instanciar uma classe –Cng em qualquer outro sistema operacional lançará uma exceção.

Da mesma forma, família –Managed de classes de criptografia (AesManaged, RijndaelManaged, SHA256Managed e assim por diante) não estão sempre disponíveis, mas por um motivo completamente diferente. O Federal Information Processing Standard 140 (FIPS) especifica padrões para algoritmos criptográficos e implementações. De redação deste artigo, ambas as –Cng –CryptoServiceProvider implementação classes e são certificados para FIPS, mas –Managed classes não são. Além disso, você pode configurar uma configuração de diretiva de grupo que permite somente algoritmos compatíveis com FIPS ser usado. Alguns dos EUA e agências do governo canadense determinam por essa configuração de diretiva. Se você quiser verificar seu computador, abrir o Editor de diretiva de grupo local (gpedit.msc), navegue até o nó computador configuração/Windows configurações/Settings/Local Policies/segurança opções de segurança e verificar o valor da configuração "criptografia de sistema: usar FIPS compatível com algoritmos para criptografia, hash e assinatura". Se esta diretiva é definida como habilitado, tentar instanciar uma classe –Managed nessa máquina lançará uma exceção.

Isso deixa família de classes –CryptoServiceProvider como o denominador comum menor garantido o funcionamento em todas as plataformas, mas essas classes também geralmente têm o pior desempenho. Você pode superar esse problema implementando uma das três sintaxes de agilidade de criptografia mencionadas anteriormente no artigo e personalizar o arquivo machine.config remapeamento para implantado máquinas com base em seu sistema operacional e configurações. Para computadores que estejam executando o Windows Vista ou posterior, pode remapear o machine.config para preferir as classes de implementação –Cng:

<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512Cng, System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>

Para computadores que executam sistemas operacionais anteriores ao Windows Vista com compatibilidade com FIPS desabilitada, nós pode remapear machine.config preferir classes –Managed:

<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512Managed"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>

Para todos os outros computadores, nós remapear para as classes –CryptoServiceProvider:

<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
     Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>

Agora, qualquer chamada para HashAlgorithm.Create("MyApplicationHash") cria a classe de implementação mais alto desempenho disponível para esse computador. Além disso, como os algoritmos são idênticos, você não precisa se preocupar sobre compatibilidade ou questões de interoperabilidade. Um hash criado para um determinado valor de entrada em uma máquina será o mesmo que um hash criado para esse mesmo valor de entrada em outra máquina, mesmo que as classes de implementação são diferentes. Isso se aplica para os outros algoritmo tipos bem: você pode criptografar uma entrada em uma máquina usando AesManaged e descriptografá-lo com êxito em um computador diferente usando AesCryptoServiceProvider.

Resumindo

O tempo e despesas de recodificação seu aplicativo em resposta a um algoritmo criptográfico desfeito, para não mencionar o perigo para os usuários até que você pode obter uma nova versão implantada, é prudente planejar para esta ocorrência e escrever seu aplicativo de maneira criptograficamente ágil. O fato de que você também pode obter um benefício de desempenho da codificação dessa maneira é glacê no bolo.

Nunca codificar algoritmos específicos ou implementações desses algoritmos em seu aplicativo. Sempre declarar algoritmos criptográficos como uma das seguintes classes de tipo de algoritmo abstrata: HashAlgorithm, SymmetricAlgorithm, AsymmetricAlgorithm, KeyedHashAlgorithm, ou HMAC.

Eu acredito que uma regra de FxCop seria verificar agilidade criptografia seria extremamente útil. Se alguém grava como uma regra e envia-lo a CodePlex ou outro repositório de código público, estarei mais feliz em dar-lhes crédito total neste espaço e na Blog do SDL.

Finalmente, eu gostaria que reconhecer Shawn Hernan da equipe de segurança do SQL Server e Shawn Farkas da equipe de segurança do CLR para seus comentários de especialistas e ajudar a produzir neste artigo.

Envie suas dúvidas e comentários para briefs@microsoft.com.

Bryan Sullivan é segurança Gerente de programa da equipe de SDL Microsoft, especializado em problemas de segurança de aplicativo da Web. Ele é autor de Ajax Security (Addison-Wesley, 2007).