Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo fornece uma visão geral dos métodos e práticas de criptografia compatíveis com o .NET, incluindo os manifestos do ClickOnce.
Introdução à criptografia
Redes públicas como a Internet não fornecem um meio de comunicação segura entre entidades. A comunicação por essas redes é suscetível a ser lida ou até modificada por terceiros não autorizados. A criptografia ajuda a proteger os dados de serem exibidos, fornece maneiras de detectar se os dados foram modificados e ajuda a fornecer um meio seguro de comunicação em canais não seguros. Por exemplo, os dados podem ser criptografados usando um algoritmo criptográfico, transmitidos em um estado criptografado e posteriormente descriptografados pela parte pretendida. Se um terceiro interceptar os dados criptografados, será difícil decifrar.
No .NET, as classes no System.Security.Cryptography namespace gerenciam muitos detalhes da criptografia para você. Alguns são wrappers para implementações do sistema operacional, enquanto outros são implementações puramente gerenciadas. Você não precisa ser um especialista em criptografia para usar essas classes. Quando você cria uma nova instância de uma das classes de algoritmo de criptografia, as chaves são geradas automaticamente para facilitar o uso e as propriedades padrão são o mais seguras e seguras possível.
Primitivos criptográficos
Em uma situação típica em que a criptografia é usada, duas partes (Alice e Bob) se comunicam por um canal não seguro. Alice e Bob querem garantir que sua comunicação permaneça incompreensível por qualquer um que possa estar ouvindo. Além disso, como Alice e Bob estão em locais remotos, Alice deve ter certeza de que as informações que recebe de Bob não foram modificadas por ninguém durante a transmissão. Além disso, ela deve garantir que as informações realmente se originem de Bob e não de alguém que esteja representando Bob.
A criptografia é usada para atingir as seguintes metas:
Confidencialidade: para ajudar a proteger a identidade ou os dados de um usuário de serem lidos.
Integridade dos dados: para ajudar a proteger os dados de serem alterados.
Autenticação: para garantir que os dados sejam originados de uma parte específica.
Não repúdio: impedir que uma determinada parte negue que enviou uma mensagem.
Para atingir essas metas, você pode usar uma combinação de algoritmos e práticas conhecidas como primitivas criptográficas para criar um esquema criptográfico. A tabela a seguir lista os primitivos criptográficos e seus usos.
| Primitivo criptográfico | Utilização |
|---|---|
| Criptografia de chave secreta (criptografia simétrica) | Executa uma transformação nos dados para impedir que eles sejam lidos por terceiros. Esse tipo de criptografia usa uma única chave secreta compartilhada para criptografar e descriptografar dados. |
| Criptografia de chave pública (criptografia assimétrica) | Executa uma transformação nos dados para impedir que eles sejam lidos por terceiros. Esse tipo de criptografia usa um par de chaves pública/privada para criptografar e descriptografar dados. |
| Assinatura criptográfica | Ajuda a verificar se os dados se originam de uma parte específica criando uma assinatura digital exclusiva para essa parte. Esse processo também usa funções de hash. |
| Hashes criptográficos | Mapeia dados de qualquer comprimento para uma sequência de bytes de comprimento fixo. Hashes são únicos em termos estatísticos; uma sequência diferente de dois bytes não produzirá o mesmo hash. |
Criptografia de Secret-Key
Algoritmos de criptografia de chave secreta usam uma única chave secreta para criptografar e descriptografar dados. Você deve proteger a chave do acesso por agentes não autorizados, pois qualquer parte que tenha a chave pode usá-la para descriptografar seus dados ou criptografar seus próprios dados, alegando que eles se originaram de você.
A criptografia de chave secreta também é conhecida como criptografia simétrica porque a mesma chave é usada para criptografia e descriptografia. Algoritmos de criptografia de chave secreta são muito rápidos (comparados com algoritmos de chave pública) e são adequados para executar transformações criptográficas em grandes fluxos de dados. Algoritmos de criptografia assimétrica, como o RSA, são limitados matematicamente na quantidade de dados que eles podem criptografar. Algoritmos de criptografia simétrica geralmente não têm esses problemas.
Um tipo de algoritmo de chave secreta chamado criptografia de bloco é usado para criptografar um bloco de dados por vez. Criptografias de bloco como DES (Data Encryption Standard), TripleDES e AES (Advanced Encryption Standard) transformam criptograficamente um bloco de entrada de n bytes em um bloco de saída de bytes criptografados. Se você quiser criptografar ou descriptografar uma sequência de bytes, precisará fazer isso bloco a bloco. Como n é pequeno (8 bytes para DES e TripleDES; 16 bytes [o padrão], 24 bytes ou 32 bytes para AES), valores de dados maiores que n precisam ser criptografados um bloco de cada vez. Os valores de dados menores que n precisam ser expandidos para n para serem processados.
Uma forma simples de cifra de bloco é chamada de modo ECB (Electronic Codebook). O modo ECB não é considerado seguro, pois não usa um vetor de inicialização para inicializar o primeiro bloco de texto sem formatação. Para uma determinada chave secreta k, uma criptografia de bloco simples que não usa um vetor de inicialização criptografará o mesmo bloco de entrada de texto sem formatação no mesmo bloco de saída do texto criptografado. Portanto, se você tiver blocos duplicados no fluxo de texto sem formatação de entrada, terá blocos duplicados no fluxo de texto codificado de saída. Esses blocos de saída duplicados alertam usuários não autorizados sobre a criptografia fraca, indicando os algoritmos que podem ter sido utilizados e os possíveis modos de ataque. O modo de criptografia do BCE é, portanto, bastante vulnerável à análise e, em última instância, à descoberta de chaves.
As classes de criptografia de bloco fornecidas na biblioteca de classes base usam um modo de encadeamento padrão chamado CBC (encadeamento de blocos de criptografia), embora você possa alterar esse padrão se desejar.
As criptografias CBC superam os problemas associados às criptografias do BCE usando um IV (vetor de inicialização) para criptografar o primeiro bloco de texto sem formatação. Cada bloco subsequente de texto sem formatação passa por uma operação OR (XOR) exclusiva bit a bit com o bloco de criptografia anterior antes de ser criptografado. Cada bloco de texto criptografado depende, portanto, de todos os blocos anteriores. Quando esse sistema é usado, cabeçalhos de mensagens comuns que podem ser conhecidos por um usuário não autorizado não podem ser usados para fazer engenharia reversa de uma chave.
Uma maneira de comprometer os dados criptografados com uma criptografia CBC é executar uma pesquisa completa de todas as chaves possíveis. Dependendo do tamanho da chave usada para executar a criptografia, esse tipo de pesquisa é muito demorado usando até mesmo os computadores mais rápidos e, portanto, é inviável. Tamanhos de chave maiores são mais difíceis de decifrar. Embora a criptografia não torne teoricamente impossível para um adversário recuperar os dados criptografados, ela aumenta o custo de fazer isso. Se levar três meses para executar uma pesquisa exaustiva para recuperar dados significativos apenas por alguns dias, o método de pesquisa exaustivo será impraticável.
A desvantagem da criptografia de chave secreta é que ela presume que duas partes concordaram com uma chave e IV e comunicaram seus valores. O IV não é considerado um segredo e pode ser transmitido sem texto sem formatação com a mensagem. No entanto, a chave deve ser mantida em segredo de usuários não autorizados. Devido a esses problemas, a criptografia de chave secreta geralmente é usada junto com a criptografia de chave pública para comunicar os valores da chave e iv de forma privada.
Supondo que Alice e Bob sejam duas partes que desejam se comunicar por um canal não seguro, eles podem usar a criptografia de chave secreta da seguinte maneira: Alice e Bob concordam em usar um algoritmo específico (AES, por exemplo) com uma chave específica e IV. Alice compõe uma mensagem e cria um fluxo de rede (talvez um pipe nomeado ou um email de rede) no qual enviar a mensagem. Em seguida, ela criptografa o texto usando a chave e o IV e envia a mensagem criptografada e IV para Bob pela intranet. Bob recebe o texto criptografado e o descriptografa usando o IV e a chave acordada anteriormente. Se a transmissão for interceptada, o interceptador não poderá recuperar a mensagem original, pois eles não conhecem a chave. Nesse cenário, somente a chave deve permanecer em segredo. Em um cenário do mundo real, Alice ou Bob gera uma chave secreta e usa a criptografia de chave pública (assimétrica) para transferir a chave secreta (simétrica) para a outra parte. Para obter mais informações sobre criptografia de chave pública, consulte a próxima seção.
O .NET fornece as seguintes classes que implementam algoritmos de criptografia de chave secreta:
HMACSHA256e HMACSHA384HMACSHA512. (Estes são algoritmos de chave secreta tecnicamente porque representam códigos de autenticação de mensagem que são calculados usando uma função de hash criptográfica combinada com uma chave secreta. Consulte Valores de Hash, mais adiante neste artigo.)
Criptografia de Public-Key
A criptografia de chave pública usa uma chave privada que deve ser mantida em segredo de usuários não autorizados e uma chave pública que pode ser tornada pública para qualquer pessoa. A chave pública e a chave privada estão matematicamente vinculadas; os dados criptografados com a chave pública só podem ser descriptografados com a chave privada e os dados assinados com a chave privada só podem ser verificados com a chave pública. A chave pública pode ser disponibilizada para qualquer pessoa; é usado para criptografar dados a serem enviados para o guardião da chave privada. Algoritmos criptográficos de chave pública também são conhecidos como algoritmos assimétricos porque uma chave é necessária para criptografar dados e outra chave é necessária para descriptografar dados. Uma regra criptográfica básica proíbe a reutilização de chave e ambas as chaves devem ser exclusivas para cada sessão de comunicação. No entanto, na prática, as chaves assimétricas geralmente são de longa duração.
Duas partes (Alice e Bob) podem usar a criptografia de chave pública da seguinte maneira: Primeiro, Alice gera um par de chaves pública/privada. Se Bob quer enviar uma mensagem criptografada para Alice, ele pede a ela sua chave pública. Alice envia sua chave pública a Bob por uma rede não seguras, e Bob usa essa chave para criptografar uma mensagem. Bob envia a mensagem criptografada para Alice, e ela a descriptografa usando sua chave privada. Se Bob recebeu a chave de Alice em um canal não seguro, como uma rede pública, Bob está aberto a um ataque man-in-the-middle. Portanto, Bob deve verificar com Alice que ele tem uma cópia correta de sua chave pública.
Durante a transmissão da chave pública de Alice, um agente não autorizado pode interceptar a chave. Além disso, o mesmo agente pode interceptar a mensagem criptografada de Bob. No entanto, o agente não pode descriptografar a mensagem com a chave pública. A mensagem pode ser descriptografada apenas com a chave privada de Alice, que não foi transmitida. Alice não usa sua chave privada para criptografar uma mensagem de resposta a Bob, porque qualquer pessoa com a chave pública pode descriptografar a mensagem. Se Alice quiser enviar uma mensagem de volta para Bob, ela pede a Bob sua chave pública e criptografa sua mensagem usando essa chave pública. Bob então descriptografa a mensagem usando sua chave privada associada.
Nesse cenário, Alice e Bob usam criptografia de chave pública (assimétrica) para transferir uma chave secreta (simétrica) e usar criptografia de chave secreta para o restante de sua sessão.
A lista a seguir oferece comparações entre algoritmos de criptografia de chave pública e chave secreta:
Algoritmos de criptografia de chave pública usam um tamanho de buffer fixo, enquanto algoritmos de criptografia de chave secreta usam um buffer de comprimento variável.
Algoritmos de chave pública não podem ser usados para encadear dados em fluxos da maneira que os algoritmos de chave secreta podem, porque apenas pequenas quantidades de dados podem ser criptografadas. Portanto, as operações assimétricas não usam o mesmo modelo de streaming que as operações simétricas.
A criptografia de chave pública tem um keyspace muito maior (intervalo de valores possíveis para a chave) do que a criptografia de chave secreta. Portanto, a criptografia de chave pública é menos suscetível a ataques exaustivos que tentam todas as chaves possíveis.
As chaves públicas são fáceis de distribuir porque não precisam ser protegidas, desde que exista alguma maneira para verificar a identidade do remetente.
Alguns algoritmos de chave pública (como RSA e DSA, mas não Diffie-Hellman) podem ser usados para criar assinaturas digitais para verificar a identidade do remetente de dados.
Algoritmos de chave pública são muito lentos em comparação com algoritmos de chave secreta e não são projetados para criptografar grandes quantidades de dados. Algoritmos de chave pública são úteis apenas para transferir quantidades muito pequenas de dados. Normalmente, a criptografia de chave pública é usada para criptografar uma chave e IV a serem usadas por um algoritmo de chave secreta. Depois que a chave e o IV são transferidos, a criptografia de chave secreta é usada para o restante da sessão.
O .NET fornece as seguintes classes que implementam algoritmos de chave pública:
A RSA permite criptografia e assinatura, mas a DSA só pode ser usada para assinatura. A DSA não é tão segura quanto a RSA e recomendamos a RSA. Diffie-Hellman pode ser usado apenas para geração de chave. Em geral, os algoritmos de chave pública são mais limitados em seus usos do que algoritmos de chave privada.
Assinaturas digitais
Algoritmos de chave pública também podem ser usados para formar assinaturas digitais. As assinaturas digitais autenticam a identidade de um remetente (se você confiar na chave pública do remetente) e ajudam a proteger a integridade dos dados. Usando uma chave pública gerada por Alice, o destinatário dos dados de Alice pode verificar se Alice a enviou comparando a assinatura digital com os dados de Alice e a chave pública de Alice.
Para usar a criptografia de chave pública para assinar digitalmente uma mensagem, Alice aplica primeiro um algoritmo de hash à mensagem para criar um resumo de mensagens. O resumo da mensagem é uma representação compacta e exclusiva de dados. Alice então criptografa o resumo da mensagem com sua chave privada para criar sua assinatura pessoal. Ao receber a mensagem e a assinatura, Bob descriptografa a assinatura usando a chave pública de Alice para recuperar o resumo da mensagem e hashes a mensagem usando o mesmo algoritmo de hash que Alice usou. Se o resumo da mensagem que Bob calcula exatamente corresponder ao resumo recebido de Alice, Bob estará assegurado de que a mensagem veio do detentor da chave privada e que os dados não foram modificados. Se Bob confia que Alice é a possuidora da chave privada, ele sabe que a mensagem veio de Alice.
Observação
Uma assinatura pode ser verificada por qualquer pessoa porque a chave pública do remetente é de conhecimento comum e normalmente está incluída no formato de assinatura digital. Esse método não mantém o sigilo da mensagem; para que a mensagem seja secreta, ela também deve ser criptografada.
O .NET fornece as seguintes classes que implementam algoritmos de assinatura digital:
Valores de hash
Algoritmos de hash mapeiam valores binários de um comprimento arbitrário para valores binários menores de um comprimento fixo, conhecidos como valores de hash. Um valor de hash é uma representação numérica de um pedaço de dados. Se você aplicar uma função de hash a um parágrafo de texto simples e alterar até mesmo uma letra do parágrafo, um hash subsequente produzirá um valor diferente. Se o hash for criptograficamente forte, seu valor mudará significativamente. Por exemplo, se um único bit de uma mensagem for alterado, uma função hash forte poderá produzir uma saída que difere em 50%. Muitos valores de entrada podem hash para o mesmo valor de saída. No entanto, é computacionalmente inviável encontrar duas entradas distintas que têm o mesmo valor.
Duas partes (Alice e Bob) podem usar uma função de hash para garantir a integridade da mensagem. Eles selecionariam um algoritmo de hash para assinar suas mensagens. Alice escreveria uma mensagem e, em seguida, criaria um hash dessa mensagem usando o algoritmo selecionado. Em seguida, seguiriam um dos seguintes métodos:
Alice envia a mensagem de texto sem formatação e a mensagem de hash (assinatura digital) para Bob. Bob recebe e faz hashes da mensagem, então compara seu valor de hash com o valor de hash que recebeu de Alice. Se os valores de hash forem idênticos, a mensagem não foi alterada. Se os valores não forem idênticos, a mensagem foi alterada depois que Alice a escreveu.
Infelizmente, esse método não estabelece a autenticidade do remetente. Qualquer um pode representar Alice e enviar uma mensagem para Bob. Eles podem usar o mesmo algoritmo de hash para assinar sua mensagem, e tudo o que Bob pode determinar é que a mensagem corresponde à sua assinatura. Esta é uma forma de um ataque man-in-the-middle. Para obter mais informações, consulte o exemplo de comunicação segura CNG (Cryptography Next Generation).
Alice envia a mensagem de texto sem formatação para Bob por meio de um canal público não seguro. Ela envia a mensagem de hash para Bob por um canal privado seguro. Bob recebe a mensagem de texto sem formatação, aplica hash a ela e compara o hash com o hash trocado privadamente. Se os hashes corresponderem, Bob sabe duas coisas:
A mensagem não foi alterada.
O remetente da mensagem (Alice) é autêntico.
Para que esse sistema funcione, Alice deve ocultar seu valor de hash original de todas as partes, exceto Bob.
Alice envia a mensagem de texto sem formatação para Bob por meio de um canal público não seguro e coloca a mensagem de hash em seu site publicamente acessível.
Esse método impede a adulteração de mensagens impedindo que qualquer pessoa modifique o valor de hash. Embora a mensagem e seu hash possam ser lidos por qualquer pessoa, o valor de hash só pode ser alterado por Alice. Um invasor que deseja representar Alice precisaria de acesso ao site de Alice.
Nenhum dos métodos anteriores impedirá que alguém leia as mensagens de Alice, pois elas são transmitidas em texto sem formatação. A segurança total normalmente requer assinaturas digitais (assinatura de mensagem) e criptografia.
O .NET fornece as seguintes classes que implementam algoritmos de hash:
O .NET também fornece MD5 e SHA1. Mas os algoritmos MD5 e SHA-1 foram considerados inseguros, e SHA-2 agora é recomendado. SHA-2 inclui SHA256, SHA384 e SHA512.
Geração de Número Aleatório
A geração de número aleatório é essencial para muitas operações criptográficas. Por exemplo, as chaves criptográficas precisam ser o mais aleatórias possível para que seja inviável reproduzi-las. Os geradores de números aleatórios criptográficos devem gerar uma saída computacionalmente inviável de prever com uma probabilidade superior a metade. Portanto, qualquer método de previsão do próximo bit de saída não deve ter um desempenho melhor do que a estimativa aleatória. As classes no .NET usam geradores de número aleatório para gerar chaves criptográficas.
A RandomNumberGenerator classe é uma implementação de um algoritmo de gerador de número aleatório.
Manifestos do ClickOnce
As seguintes classes de criptografia permitem obter e verificar informações sobre assinaturas de manifesto para aplicativos implantados usando a tecnologia ClickOnce:
A classe ManifestSignatureInformation obtém informações sobre uma assinatura de manifesto quando você usa suas sobrecargas de método VerifySignature.
Você pode usar a ManifestKinds enumeração para especificar quais manifestos devem ser verificados. O resultado da verificação é um dos valores de uma enumeração SignatureVerificationResult.
A classe ManifestSignatureInformationCollection fornece uma coleção somente leitura de objetos ManifestSignatureInformation das assinaturas verificadas.
Além disso, as seguintes classes fornecem informações de assinatura específicas:
StrongNameSignatureInformation contém as informações de assinatura de nome forte de um manifesto.
AuthenticodeSignatureInformation representa as informações de assinatura do Authenticode para um manifesto.
TimestampInformation contém informações sobre o timestamp em uma assinatura Authenticode.
TrustStatus fornece uma maneira simples de verificar se uma assinatura Authenticode é confiável.
Classes CNG (Cryptography Next Generation)
As classes CNG (Cryptography Next Generation) fornecem um wrapper gerenciado em torno das funções CNG nativas. (CNG é a substituição de CryptoAPI.) Essas classes têm "Cng" como parte de seus nomes. O elemento central das classes de wrapper CNG é a classe contêiner de chave CngKey, que abstrai o armazenamento e o uso de chaves CNG. Essa classe permite armazenar um par de chaves ou uma chave pública com segurança e fazer referência a ela usando um nome de cadeia de caracteres simples. A classe de assinatura ECDsaCng baseada em curva elíptica e a classe de criptografia ECDiffieHellmanCng podem usar objetos CngKey.
A CngKey classe é usada para uma variedade de operações adicionais, incluindo abertura, criação, exclusão e exportação de chaves. Ele também fornece acesso ao identificador de chave subjacente a ser usado ao chamar funções nativas diretamente.
O .NET também inclui uma variedade de classes CNG de suporte, como a seguinte:
CngProvider mantém um provedor de armazenamento chave.
CngAlgorithm mantém um algoritmo CNG.
CngProperty mantém propriedades de chave usadas com frequência.
Consulte também
- Modelo de criptografia – Descreve como a criptografia é implementada na biblioteca de classes base.
- Criptografia multiplataforma
- Vulnerabilidades de temporização com descriptografia simétrica no modo CBC usando preenchimento
- ASP.NET Core Data Protection