Hashing & berichtauthenticatie

Een cryptografische hash zet een willekeurige hoeveelheid gegevens om in een korte digest van vaste grootte. Dezelfde invoer levert altijd dezelfde digest op, een andere invoer (zelfs met één gewijzigd bit) levert een volledig andere digest op, en er is geen praktische manier om een invoer te vinden die een gekozen digest oplevert. Een message authentication code (MAC) voegt een geheime sleutel aan dat idee toe, zodat de digest ook bewijst dat de gegevens niet zijn gewijzigd door iemand die de sleutel niet bezit.

Alle functies op deze pagina ontvangen en geven TBytes terug en bevinden zich in sgcCrypto_SHA2, sgcCrypto_Keccak, sgcCrypto_Blake2b, sgcCrypto_Blake2s, sgcCrypto_SipHash, sgcCrypto_HMAC, sgcCrypto_CMAC en sgcCrypto_Poly1305.

SHA-2

De hashfamilie achter TLS-certificaten, codeondertekening en de meeste protocollen die vandaag in productie zijn. Gebruik SHA-256 tenzij iets specifieks om een andere grootte vraagt.


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 en KMAC

SHA-3 is gebaseerd op een andere constructie (Keccak) dan SHA-2, zodat een zwakte in de ene familie niet overslaat naar de andere, wat de reden is waarom protocollen die langetermijnzekerheid nodig hebben vaak beide voorschrijven. SHAKE128 en SHAKE256 zijn extendable output functions: in plaats van een vaste digestgrootte vraagt u zoveel bytes als u nodig heeft, en een kortere uitvoer is altijd een prefix van een langere uitvoer voor dezelfde invoer. ML-KEM, ML-DSA en SLH-DSA (zie Post-quantumcryptografie) zijn allemaal intern op SHAKE gebaseerd. KMAC is de native message authentication code van SHA-3, gebaseerd op 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 en BLAKE2s

BLAKE2 is sneller dan SHA-2 en SHA-3 in software, terwijl het dezelfde beveiligingsmarge biedt, en het accepteert rechtstreeks een optionele sleutel, zonder de HMAC-constructie. BLAKE2b richt zich op 64-bit platforms met digests tot 512 bit; BLAKE2s richt zich op 32-bit en embedded platforms met digests tot 256 bit. Een kortere digest is geen afkapping van de volledige digest, de lengte wordt in de hash zelf verwerkt, zodat een programma niet van grootte kan wisselen en dezelfde uitvoer kan verwachten.


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

SipHash-2-4 is een snelle, gekeyede hash die is ontworpen voor hashtable-lookups. De taak ervan is te voorkomen dat een aanvaller uw toepassing gekozen invoerwaarden voedt die allemaal in dezelfde bucket terechtkomen en zo een O(1)-lookup in een O(n)-lookup veranderen, een denial-of-service-techniek die bekendstaat als hash flooding. Het gebruikt exact 16 bytes sleutel en produceert een tag van 8 bytes; het is geen general purpose MAC en mag niet worden gebruikt om berichten te authenticeren.


function sgcSipHash24(const aKey, aData: TBytes): TBytes;

HMAC

HMAC zet elk van de bovenstaande hashes om in een message authentication code. Het is de standaardkeuze wanneer de onderliggende hash geen sleutel rechtstreeks accepteert (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

CMAC bouwt een MAC op basis van een blokcijfer in plaats van een hash. Gebruik het waar een protocol AES-CMAC met naam voorschrijft (dit komt vaak voor in smartcard- en IoT-specificaties); anders is HMAC-SHA256 de gebruikelijkere standaardkeuze.


function sgcAES_CMAC(const aKey, aData: TBytes): TBytes;
function sgcAES_CMAC_Verify(const aKey, aData, aTag: TBytes): Boolean;

Poly1305

Poly1305 is een eenmalige authenticator: hij mag nooit twee keer met dezelfde sleutel worden gebruikt. In de praktijk wordt hij niet rechtstreeks aangeroepen, hij is de authenticatiehelft van de ChaCha20-Poly1305- en XChaCha20-Poly1305 AEAD-cijfers op de pagina Symmetrische versleuteling, die voor elk bericht een verse eenmalige sleutel afleiden.


function sgcPoly1305(const aKey, aData: TBytes): TBytes;
function sgcPoly1305_Verify(const aKey, aData, aTag: TBytes): Boolean;

Een MAC of een wachtwoordhash vergelijken

Vergelijk nooit twee tags of digests met een gewone =-vergelijking wanneer een van beide afkomstig is van een niet-vertrouwde bron. Een byte-voor-byte-vergelijking die stopt zodra ze een verschil vindt, kost meetbaar minder tijd naarmate het verschil eerder optreedt, en dat is voor een aanvaller al voldoende signaal om over veel pogingen heen, byte voor byte, een geldige tag te vervalsen. Gebruik in plaats daarvan de constant time compare uit sgcCrypto_Encoding, vermeld onder Encodering & hulpprogramma's op de overzichtspagina Cryptografie.


function sgcConstantTimeEquals(const aLeft, aRight: TBytes): Boolean;

RIPEMD-160

Een 160 bit digest van het Europese RIPE-project, in sgcCrypto_Legacy maar niet verouderd in de zin die de sectie hieronder bedoelt. Het is niet gebroken zoals MD5 en SHA-1 dat zijn, maar het is trager dan SHA-256 en biedt minder beveiligingsmarge, dus het hoort thuis waar een formaat het specifiek voorschrijft, niet als standaardkeuze. Bitcoin en elke keten die ervan afstamt, gebruikt het voor adressen, gelaagd over SHA-256. HMAC-RIPEMD160 is 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;

Verouderde hashes

sgcCrypto_Legacy biedt MD4, MD5 en HMAC-MD5. Alle drie zijn als beveiligingsprimitieven gebroken: voor zowel MD4 als MD5 zijn praktische botsingen gepubliceerd. Ze bestaan alleen voor interoperabiliteit met oudere protocollen en bestandsformaten die ze met naam voorschrijven (bijvoorbeeld NTLM-authenticatie). Kies ze niet voor iets nieuws; gebruik in plaats daarvan SHA-256 of BLAKE2b.


function sgcMD4(const aData: TBytes): TBytes;
function sgcMD5(const aData: TBytes): TBytes;
function sgcHMAC_MD5(const aKey, aData: TBytes): TBytes;