.NET

12 mar, 2024

Novidades do .NET 9: melhorias em criptografia com CryptographicOperations.HashData()

Publicidade

Neste novo artigo dou continuidade à série que venho produzindo sobre novidades trazidas pelo .NET 9, utilizando para isto recursos já disponibilizados pelo Preview 1. Caso deseje consultar ou mesmo rever as postagens anteriores, acesse os links a seguir:

Novidades do .NET 9: serialização utilizando JsonSerializerOptions.Web (no padrão do ASP.NET Core)

.NET 9: primeiros testes com o Preview 1 + método CountBy em LINQ

Em um vídeo recente do Canal .NET no YouTube apresentei ainda algumas novidades relacionadas à serialização JSON, as quais também integram o Preview 1 do .NET 9:

Versões anteriores ao .NET 9 contavam com implementações simplificadas chamadas “one-shot”, descomplicando o uso de funções hash e outras capacidades baseadas em diversos algoritmos de criptografia. Dentre os benefícios proporcionados por esses métodos one-shot (acionados a partir de tipos pertencentes ao namespace System.Security.Cryptography) temos otimizações de performance, além de reduções ou mesmo a eliminação de operações alocando recursos.

Os trechos de código a seguir demonstram a utilização dessas implementações one-shot, em exemplos que empregaram os tipos SHA256SHA384SHA512 e MD5 através de chamadas ao método HashData:

var content = Encoding.ASCII.GetBytes("Testes com .NET 9");

Console.WriteLine();
Console.WriteLine("*** Versoes one-shot usando tipos que representam algoritmos ***");
Console.WriteLine("SHA256.HashData() = " +
JsonSerializer.Serialize(SHA256.HashData(content)));
Console.WriteLine("SHA384.HashData() = " +
JsonSerializer.Serialize(SHA384.HashData(content)));
Console.WriteLine("SHA512.HashData() = " +
JsonSerializer.Serialize(SHA512.HashData(content)));
Console.WriteLine("MD5.HashData() = " +
JsonSerializer.Serialize(MD5.HashData(content)));

Com o .NET 9 temos uma nova alternativa para flexibilizar implementações envolvendo criptografia: o método HashData, disponibilizado pelo tipo CryptographicOperations (também presente no namespace System.Security.Cryptography). Essa nova funcionalidade recebe como parâmetro um valor vinculado ao struct HashAlgorithmName (namespace System.Security.Cryptography), permitindo até mesmo que uma única chamada a tal versão do método estático HashData seja usada com vários algoritmos.

A próxima listagem traz os exemplos anteriores refatorados, já utilizando o método HashData de CryptographicOperations:

Console.WriteLine();
Console.WriteLine("*** Testes com CryptographicOperations.HashData() ***");
Console.WriteLine("HashAlgorithmName.SHA256 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.SHA256, content)));
Console.WriteLine("HashAlgorithmName.SHA384 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.SHA384, content)));
Console.WriteLine("HashAlgorithmName.SHA512 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.SHA512, content)));
Console.WriteLine("HashAlgorithmName.MD5 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.MD5, content)));

Na listagem a seguir temos um exemplo de Console Application que emprega essas 2 possibilidades (nova implementação em CryptographicOperations, além das versões específicas de HashData() por algoritmo):

using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.Json;
using System.Text;

Console.WriteLine("***** Testes com .NET 9 | CryptographicOperations.HashData API *****");
Console.WriteLine($"Versao do .NET em uso: {RuntimeInformation
    .FrameworkDescription} - Ambiente: {Environment.MachineName} - Kernel: {Environment
    .OSVersion.VersionString}");

var content = Encoding.ASCII.GetBytes("Testes com .NET 9");

Console.WriteLine();
Console.WriteLine("*** Versoes one-shot usando tipos que representam algoritmos ***");
Console.WriteLine("SHA256.HashData() = " +
    JsonSerializer.Serialize(SHA256.HashData(content)));
Console.WriteLine("SHA384.HashData() = " +
    JsonSerializer.Serialize(SHA384.HashData(content)));
Console.WriteLine("SHA512.HashData() = " +
    JsonSerializer.Serialize(SHA512.HashData(content)));
Console.WriteLine("MD5.HashData() = " +
    JsonSerializer.Serialize(MD5.HashData(content)));

Console.WriteLine();
Console.WriteLine("*** Testes com CryptographicOperations.HashData() ***");
Console.WriteLine("HashAlgorithmName.SHA256 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.SHA256, content)));
Console.WriteLine("HashAlgorithmName.SHA384 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.SHA384, content)));
Console.WriteLine("HashAlgorithmName.SHA512 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.SHA512, content)));
Console.WriteLine("HashAlgorithmName.MD5 = " +
    JsonSerializer.Serialize(CryptographicOperations.HashData(HashAlgorithmName.MD5, content)));

A imagem seguinte apresenta os resultados produzidos por esta aplicação, em que se notam os mesmos valores de hashes para os 2 tipos de implementação:

Clique nesta imagem para visualizar com uma melhor resolução

Esse projeto com os testes pode ser encontrado no GitHub:

https://github.com/renatogroffe/DotNet9-ConsoleApp-CryptographicOperations-HashData/tree/main

Caso achem útil esta solução, peço por favor um ⭐️ no repositório apoiando. Fica também o convite para que vocês me sigam lá no GitHub!