Um hash criptográfico transforma qualquer quantidade de dados em um digest curto e de tamanho fixo. A mesma entrada sempre produz o mesmo digest, uma entrada diferente (mesmo que apenas um bit mude) produz um digest completamente diferente, e não há nenhuma forma prática de encontrar uma entrada que produza um digest escolhido. Um código de autenticação de mensagem (MAC) acrescenta uma chave secreta a essa ideia, de modo que o digest também prova que os dados não foram alterados por alguém que não possui a chave.
Todas as funções desta página recebem e retornam TBytes e vivem em sgcCrypto_SHA2, sgcCrypto_Keccak, sgcCrypto_Blake2b, sgcCrypto_Blake2s, sgcCrypto_SipHash, sgcCrypto_HMAC, sgcCrypto_CMAC e sgcCrypto_Poly1305.
SHA-2
A família de hash por trás dos certificados TLS, da assinatura de código e da maioria dos protocolos em produção hoje. Use SHA-256 a menos que algo específico peça um tamanho diferente.
function sgcSHA1(const aData: TBytes): TBytes;
function sgcSHA224(const aData: TBytes): TBytes;
function sgcSHA256(const aData: TBytes): TBytes;
function sgcSHA384(const aData: TBytes): TBytes;
function sgcSHA512(const aData: TBytes): TBytes;
SHA-3, SHAKE, cSHAKE e KMAC
O SHA-3 é construído sobre uma construção diferente (Keccak) da do SHA-2, de modo que uma fraqueza em uma família não se propaga para a outra, e é por isso que protocolos que precisam de garantia de longo prazo frequentemente especificam ambas. SHAKE128 e SHAKE256 são funções de saída extensível: em vez de um tamanho de digest fixo, você pede quantos bytes precisar, e uma saída mais curta é sempre um prefixo de uma saída mais longa a partir da mesma entrada. ML-KEM, ML-DSA e SLH-DSA (veja Criptografia Pós-Quântica) são todos construídos internamente sobre SHAKE. KMAC é o código de autenticação de mensagem nativo do SHA-3, construído sobre cSHAKE.
function sgcSHA3_224(const aData: TBytes): TBytes;
function sgcSHA3_256(const aData: TBytes): TBytes;
function sgcSHA3_384(const aData: TBytes): TBytes;
function sgcSHA3_512(const aData: TBytes): TBytes;
function sgcSHAKE128(const aData: TBytes; aLen: Integer): TBytes;
function sgcSHAKE256(const aData: TBytes; aLen: Integer): TBytes;
function sgcKMAC128(const aKey, aData: TBytes; aLen: Integer; const aCustom: TBytes): TBytes;
function sgcKMAC256(const aKey, aData: TBytes; aLen: Integer; const aCustom: TBytes): TBytes;
BLAKE2b e BLAKE2s
O BLAKE2 é mais rápido que o SHA-2 e o SHA-3 em software, mantendo a mesma margem de segurança, e aceita uma chave opcional diretamente, sem a construção HMAC. O BLAKE2b tem como alvo plataformas de 64 bits com digests de até 512 bits; o BLAKE2s tem como alvo plataformas de 32 bits e embarcadas com digests de até 256 bits. Um digest mais curto não é um truncamento do digest completo, o tamanho é misturado ao próprio hash, de modo que um programa não pode trocar de tamanho e esperar uma saída correspondente.
function sgcBlake2b(const aData: TBytes; aDigestLen: Integer = 64): TBytes;
function sgcBlake2b_Keyed(const aKey, aData: TBytes; aDigestLen: Integer = 64): TBytes;
function sgcBlake2s(const aData: TBytes; aDigestLen: Integer = 32): TBytes;
function sgcBlake2s_Keyed(const aKey, aData: TBytes; aDigestLen: Integer = 32): TBytes;
SipHash
O SipHash-2-4 é um hash rápido e com chave, projetado para buscas em tabelas hash. Sua tarefa é impedir que um atacante alimente sua aplicação com entradas escolhidas que caiam todas no mesmo bucket, transformando uma busca O(1) em O(n), uma técnica de negação de serviço conhecida como hash flooding. Ele recebe exatamente 16 bytes de chave e produz uma tag de 8 bytes; não é um MAC de propósito geral e não deve ser utilizado para autenticar mensagens.
function sgcSipHash24(const aKey, aData: TBytes): TBytes;
HMAC
O HMAC transforma qualquer um dos hashes acima em um código de autenticação de mensagem. É a escolha padrão quando o hash subjacente não aceita uma chave diretamente (SHA-1, SHA-2).
function sgcHMAC_SHA1(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA256(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA384(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA512(const aKey, aData: TBytes): TBytes;
var
oTag: TBytes;
begin
oTag := sgcHMAC_SHA256(TBytes(oKey), TBytes(oMessage));
end;
AES-CMAC
O CMAC constrói um MAC a partir de uma cifra de bloco em vez de um hash. Use-o onde um protocolo especificar AES-CMAC pelo nome (é comum em especificações de smart card e IoT); caso contrário, HMAC-SHA256 é o padrão mais usual.
function sgcAES_CMAC(const aKey, aData: TBytes): TBytes;
function sgcAES_CMAC_Verify(const aKey, aData, aTag: TBytes): Boolean;
Poly1305
O Poly1305 é um autenticador de uso único: nunca deve ser utilizado duas vezes com a mesma chave. Na prática, ele não é chamado diretamente, é a metade de autenticação das cifras AEAD ChaCha20-Poly1305 e XChaCha20-Poly1305 na página Criptografia Simétrica, que derivam uma nova chave de uso único para cada mensagem.
function sgcPoly1305(const aKey, aData: TBytes): TBytes;
function sgcPoly1305_Verify(const aKey, aData, aTag: TBytes): Boolean;
Comparando um MAC ou um hash de senha
Nunca compare duas tags ou digests com um simples = quando um deles vier de uma fonte não confiável. Uma comparação byte a byte que retorna assim que encontra uma divergência leva um tempo mensuravelmente menor quanto mais cedo a divergência ocorrer, o que já é sinal suficiente para um atacante forjar uma tag válida um byte de cada vez ao longo de muitas tentativas. Use a comparação em tempo constante de sgcCrypto_Encoding em vez disso, listada em Codificação & utilitários na página de visão geral Criptografia.
function sgcConstantTimeEquals(const aLeft, aRight: TBytes): Boolean;
RIPEMD-160
Um digest de 160 bits do projeto europeu RIPE, presente em sgcCrypto_Legacy, mas não legado no sentido em que a seção abaixo usa o termo. Ele não está quebrado como o MD5 e o SHA-1 estão, mas é mais lento que o SHA-256 e oferece menos margem de segurança, portanto pertence aos casos em que um formato o exige especificamente pelo nome, e não como escolha padrão. O Bitcoin, e toda blockchain descendente dele, o utiliza para gerar endereços, sobreposto ao SHA-256. O HMAC-RIPEMD160 é a RFC 2286.
function sgcRIPEMD160(const aData: TBytes): TBytes;
function sgcHMAC_RIPEMD160(const aKey, aData: TBytes): TBytes;
var
oHash160: TBytes;
begin
{ the Bitcoin address digest: RIPEMD-160 over SHA-256 }
oHash160 := sgcRIPEMD160(sgcSHA256(oPublicKey));
end;
Hashes legados
sgcCrypto_Legacy fornece MD4, MD5 e HMAC-MD5. Os três estão quebrados como primitivas de segurança: colisões práticas já foram publicadas tanto para MD4 quanto para MD5. Eles existem apenas para interoperar com protocolos e formatos de arquivo mais antigos que os especificam pelo nome (por exemplo, autenticação NTLM). Não os escolha para nada novo; use SHA-256 ou BLAKE2b em vez disso.
function sgcMD4(const aData: TBytes): TBytes;
function sgcMD5(const aData: TBytes): TBytes;
function sgcHMAC_MD5(const aKey, aData: TBytes): TBytes;