Hash funktion

En hash-funktion ( eng.  hash-funktion fra hash  - "omdannes til hakket kød", "hash" [1] ), eller en foldningsfunktion  er en funktion, der konverterer et array af inputdata af vilkårlig længde til en output- bitstreng af en indstillet længde, udført af en bestemt algoritme . Transformationen udført af hash-funktionen kaldes hashing . Inputdataene kaldes input-arrayet, " tasten " eller " meddelelsen ". Resultatet af konverteringen kaldes " hash ", " hash code ", " hash sum ", "besked oversigt .

Hash-funktioner bruges i følgende tilfælde:

I det generelle tilfælde (ifølge Dirichlets princip ) er der ingen en-til-en overensstemmelse mellem hash-koden og de originale data. De værdier, der returneres af hash-funktionen, er mindre forskellige end værdierne for input-arrayet. Det tilfælde, hvor en hash-funktion omdanner mere end ét input-array til de samme resuméer, kaldes en " kollision ". Kollisionssandsynlighed bruges til at evaluere kvaliteten af ​​hash-funktioner.

Der er mange hashing-algoritmer med forskellige egenskaber. Eksempler på ejendom:

Valget af den ene eller anden hash-funktion bestemmes af det specifikke problem, der skal løses. Det enkleste eksempel på en hashfunktion er indramning af data med en cyklisk redundanskode ( CRC , cyklisk redundanskode ) . 

Historie

Kryptering af beskeder uden mulighed for entydig dekryptering, men kun for at bekræfte forfatterens prioritet, har været brugt i lang tid.

Galileo Galilei observerede Saturns ringe , som han forvekslede med "ører". Da han ikke var sikker, men ville hævde sin prioritet, udgav han en besked med bogstaverne omarrangeret: smaismrmilmepoetaleumibunenugttauiras . I 1610 afslørede han den oprindelige sætning: Altissimum planetam tergeminum obseruaui , som på latin betyder "han observerede den højeste planet i triplet." På tidspunktet for offentliggørelsen af ​​den første meddelelse blev den oprindelige sætning således ikke afsløret, men der blev skabt en mulighed for at bekræfte den senere.

I midten af ​​1650'erne så Christian Huygens ringene og udgav en besked med bogstaver ordnet alfabetisk: aaaaaaaacccccdeeeeeeghiiiiiiillllmmnnnnnnnnnooooppqrrsttttuuuuuu . Efter nogen tid blev den originale sætning også udgivet: Annulo cingitur, tenui plano, nusquam cohaerente, ad eclipticam inclinato  - "Omgivet af en tynd, flad ring, ingen steder ophængt, hælder til ekliptika ". Dette tilfælde adskiller sig fra brugen af ​​en hash-funktion, herunder målet om senere at bekræfte en eller anden uafklaret besked, kun ved at output-meddelelsen ikke har en fast længde, men er bestemt af længden af ​​input. Faktisk er alfabetisering af bogstaverne i den originale besked en hash-funktion, men kun med et resultat uden fast længde.

I januar 1953 foreslog Hans Peter Luhn ( tysk:  Hans Peter Luhn ) (medarbejder hos IBM ) "hash-kodning". Donald Knuth krediterer Hans som den første til at fremsætte den systematiske idé om "hashing".

I 1956 var Arnold Dumey i hans  Computere og automatisering den første til at beskrive ideen om "hashing", som de fleste programmører kender det i dag. Dumi betragtede "hashing" som en løsning på "ordbogsproblemet", foreslog at bruge resten af ​​division med et primtal som en "hash-adresse" [2] .

I 1957 publicerede W. Wesley Peterson en artikel i IBM Journal of Research and Development om at finde tekst i store filer . Dette arbejde betragtes som det første "seriøse" arbejde med "hashing". I artiklen definerede Wesley "åben adressering" og påpegede faldet i ydeevne ved sletning. Seks år senere udkom Werner Buchholz ( tysk: Werner Buchholz ) værk, hvor der blev udført en omfattende undersøgelse af "hash-funktioner". I løbet af de næste par år blev "hashing" meget brugt, men der blev ikke publiceret noget væsentligt værk.   

I 1967 omtales "hashing" i moderne forstand i bogen Principles of Digital Computing Systems af Herbert Hellermann [3] . I 1968 offentliggjorde Robert Morris en  stor undersøgelse om "hashing" i tidsskriftet Communications of the ACM . Dette arbejde betragtes som en " nøgle " publikation, der introducerer begrebet "hashing" i videnskabelig cirkulation og fastlægger udtrykket "hash", som tidligere kun blev brugt af specialister ( jargon ).

Indtil begyndelsen af ​​1990'erne, i den russisksprogede litteratur, takket være Andrei Petrovich Ershovs værker , blev ordet "arrangement" brugt som en ækvivalent til udtrykket "hashing" , og udtrykket "konflikt" blev brugt til " kollisioner " ( A.P. Ershov brugte "arrangement" siden 1956 ). Den russisksprogede udgave af 1989 af Algorithms and Data Structures af Niklaus Wirth bruger også udtrykket "arrangement". Det blev også foreslået at navngive metoden med et andet russisk ord: " okroshka ". Ingen af ​​disse muligheder har dog slået rod, og i russisk litteratur bruges udtrykket "hashing" overvejende [4] .

Typer af "hash-funktioner"

En "god" hashfunktion skal opfylde to egenskaber :

Lad os introducere notationen:

Det er:

.

Som et eksempel på en "dårlig" hash-funktion kan vi nævne funktionen med , som matcher et ti-cifret naturligt tal med tre cifre valgt fra midten af ​​det tyve-cifrede kvadrat af tallet . Det ser ud til, at værdierne af "hash-koder" skal være jævnt fordelt mellem " 000 " og " 999 ", men for " rigtige " data er dette kun sandt, hvis " tasterne " ikke har et "stort" antal nuller til venstre eller højre [4] .

Lad os overveje nogle enkle og pålidelige implementeringer af "hash-funktioner".

"Hash-funktioner" baseret på division

1. "Hash-kode" som resten af ​​division med antallet af alle mulige "hash-koder"

Hash-funktionen kan beregne "hash" som resten af ​​at dividere input med :

,

hvor  er antallet af alle mulige hashes (outputdata).

Samtidig er det indlysende, at for lige vil værdien af ​​funktionen være lige for lige og ulige - for ulige . Brug heller ikke computerens talsystem som basisgrad , da "hash-koden" kun afhænger af nogle få cifre i nummeret til højre, hvilket vil føre til et stort antal kollisioner . I praksis vælges normalt en simpel ; i de fleste tilfælde er dette valg ganske tilfredsstillende.

2. "Hash-kode" som et sæt koefficienter for det resulterende polynomium

En hashfunktion kan udføre modulo to -deling af inputdataene med et polynomium . I denne metode skal det være en potens af to, og binære nøgler ( ) er repræsenteret som polynomier , som en "hash-kode" værdierne af koefficienterne for polynomiet opnået som resten af ​​at dividere inputdataene med en præ -valgte gradspolynomier " tages" :

Med det rigtige valg er fraværet af kollisioner mellem næsten identiske nøgler garanteret [4] .

"Hash-funktioner" baseret på multiplikation

Vi betegner med symbolet antallet af tal, der kan repræsenteres af et maskinord . For eksempel for 32-bit computere, der er kompatible med IBM PC'en , .

Lad os vælge en konstant , så den er coprime med . Så kan en hashfunktion ved hjælp af multiplikation se sådan ud:

I dette tilfælde på en computer med et binært talsystem er en potens af to, og vil bestå af de høje bits i højre halvdel af produktet .

En fordel ved hash-funktioner baseret på division og multiplikation er den fordelagtige brug af ikke-tilfældigheden af ​​rigtige nøgler. For eksempel, hvis tasterne er en aritmetisk progression (for eksempel rækkefølgen af ​​navne "Navn 1", "Navn 2", "Navn 3"), vil en hash-funktion, der bruger multiplikation, kortlægge den aritmetiske progression til en omtrentlig aritmetisk progression af forskellige hashværdier, hvilket vil reducere antallet af kollisioner sammenlignet med en tilfældig situation [4] .

En af de hash-funktioner, der bruger multiplikation, er hash-funktionen, der bruger Fibonacci -hashing . Fibonacci hashing er baseret på egenskaberne af det gyldne snit . Som konstant vælges her et heltal, tættest på og coprime til , hvor  er det gyldne snit [4] .

Strengehashing med variabel længde

Ovenstående metoder er også anvendelige, når det er nødvendigt at overveje nøgler, der består af flere ord eller nøgler af variabel længde.

For eksempel kan du kombinere ord til ét ved at bruge modulo-addition eller XOR- operationen . En af de algoritmer, der fungerer efter dette princip, er Pearson-hash-funktionen.

Pearson hashing  er en algoritme foreslået af Peter  Pearson til processorer med 8-bit registre, hvis opgave er hurtigt at konvertere en streng af vilkårlig længde til en hash-kode. Som input modtager funktionen et ord , der består af tegn, hver 1 byte i størrelse, og returnerer en værdi i området fra 0 til 255. I dette tilfælde afhænger værdien af ​​hashkoden af ​​hvert tegn i inputordet.

Algoritmen kan beskrives med følgende pseudokode, som tager en streng som input og bruger en permutationstabel :

h := 0 for hver c i W -løkkeindeks := h xeller c h := T[indeks] endeløkke retur h

Blandt fordelene ved algoritmen:

  • let beregning;
  • fraværet af sådanne inputdata, for hvilke sandsynligheden for en kollision er størst;
  • muligheden for modifikation til en ideel hashfunktion [5] .

Som en alternativ metode til hashing af nøgler bestående af tegn ( ), kan vi tilbyde beregningen

[fire]

Perfekt hashing

En ideel hash-funktion ( engelsk  perfekt hash-funktion ) er en funktion , der kortlægger hver tast fra sættet til et sæt heltal uden kollisioner . I matematik kaldes en sådan transformation en injektiv kortlægning.

Beskrivelse
  1. En funktion kaldes en ideel hashfunktion, hvis den er injektiv på .
  2. En funktion kaldes den minimale ideelle hashfunktion for, hvis den er en perfekt hashfunktion og .
  3. For et heltal kaldes funktionen en -perfekt hash-funktion (k-PHF) for hvis for hver vi har .

Ideel hashing bruges, når det er nødvendigt at tildele en unik identifikator til en nøgle uden at gemme nogen information om nøglen. Et eksempel på brugen af ​​ideel (eller rettere , ideel) hashing: at placere hashes forbundet med data, der er gemt i stor og langsom hukommelse, i lille og hurtig hukommelse. Blokstørrelsen kan vælges, så de nødvendige data læses fra den langsomme hukommelse i én anmodning. En lignende tilgang bruges for eksempel i hardware-routere . Ideel hashing bruges også til at fremskynde arbejdet med algoritmer på grafer, hvis grafrepræsentationen ikke passer i hovedhukommelsen [6] .

Universal hashing

Universal hashing kaldes hashing, hvor der ikke bruges én specifik hash-funktion, men en hash-funktion vælges fra en given familie ifølge en tilfældig algoritme . Universal hashing er normalt kendetegnet ved et lavt antal kollisioner; det bruges for eksempel ved implementering af hashtabeller og i kryptografi.

Beskrivelse

Antag, at vi ønsker at kortlægge nøgler fra mellemrum til tal . Ved input modtager algoritmen data fra et eller andet sæt dimensioner . Sættet kendes ikke på forhånd. Som regel skal algoritmen give det mindste antal kollisioner , hvilket er svært at opnå ved brug af en bestemt hashfunktion. Antallet af kollisioner kan reduceres ved at vælge en hash-funktion tilfældigt, hver gang du skal hash. Hash-funktionen er valgt fra et specifikt sæt af hash-funktioner kaldet den universelle familie [7] .

Metoder til håndtering af kollisioner

En kollision (nogle gange en konflikt [2] eller kollision) er et tilfælde, hvor en hashfunktion for forskellige inputblokke returnerer de samme hashkoder.

Teknikker til håndtering af kollisioner i hashtabeller

De fleste af de første artikler, der beskrev hashing, handlede om metoder til at håndtere kollisioner i hashtabeller. Så blev der brugt hash-funktioner, når man søgte efter tekst i store filer. Der er to hovedmetoder til at håndtere kollisioner i hashtabeller:

  1. kæde metode (direkte link metode);
  2. åben adressemetode.

Når du bruger kædemetoden, gemmer hashtabellen parrene " linked list of keys" - "hash code". For hver nøgle beregnes en hash-kode af hash-funktionen; hvis hashkoden blev opnået tidligere (for en anden nøgle), tilføjes nøglen til den eksisterende liste over nøgler parret med hashkoden; ellers oprettes et nyt par "nøgleliste" - "hash-kode", og nøglen føjes til den oprettede liste. Generelt, hvis der er nøgler og lister, vil den gennemsnitlige størrelse af hash-tabellen være . I dette tilfælde, når du søger gennem tabellen, sammenlignet med det tilfælde, hvor søgningen udføres sekventielt, vil den gennemsnitlige mængde arbejde falde med omkring en faktor.

Når du bruger den åbne adresseringsmetode, gemmer hash-tabellen nøgle-hash-kodepar. For hver nøgle beregnes en hash-kode af hash-funktionen; parret "nøgle" - "hash-kode" er gemt i tabellen. I dette tilfælde, når der søges gennem tabellen, sammenlignet med det tilfælde, hvor linkede lister bruges, bruges links ikke, en sekventiel opregning af "nøgle" - "hash-kode" parrene udføres, optællingen stopper efter den nødvendige nøgle er fundet. Rækkefølgen, hvori tabelcellerne scannes, kaldes probesekvensen [4] .

Kryptografisk salt

For at beskytte adgangskoder og digitale signaturer mod forfalskning er der lavet flere metoder, der virker, selvom kryptanalytikeren ved, hvordan man konstruerer kollisioner til den anvendte hash-funktion. En af disse metoder er at tilføje et såkaldt kryptografisk "salt" til inputdataene  - en streng af tilfældige data; nogle gange tilføjes "salt" til hash-koden også. Tilføjelse af tilfældige data gør det meget vanskeligere at analysere de resulterende hashtabeller. Denne metode bruges for eksempel, når du gemmer adgangskoder i UNIX-lignende operativsystemer .

Anvendelser af hash-funktioner

Hash-funktioner er meget brugt i kryptografi.

Hashen bruges som en nøgle i mange datastrukturer - hashtabeller , Bloom-filtre og kartesiske træer .

Kryptografiske hash-funktioner

Blandt de mange eksisterende hash-funktioner er det sædvanligt at udskille kryptografisk sikre dem, der bruges i kryptografi , da der stilles yderligere krav til dem. For at en hashfunktion kan betragtes som kryptografisk sikker, skal den opfylde tre grundlæggende krav, som de fleste anvendelser af hashfunktioner i kryptografi er baseret på:

  • irreversibilitet : for en given hashværdi m , burde det være beregningsmæssigt umuligt at finde en datablok for hvilken ;
  • modstand mod kollisioner af den første art : for en given meddelelse M , burde det være beregningsmæssigt umuligt at finde en anden meddelelse N for hvilken ;
  • modstand mod type 2-kollisioner : det burde være beregningsmæssigt umuligt at opfange et par beskeder , der har samme hash.

Disse krav er ikke uafhængige:

  • den reversible funktion er ustabil over for kollisioner af den første og anden art;
  • en funktion, der er ustabil over for kollisioner af den første type, er ustabil over for kollisioner af den anden type; det omvendte er ikke sandt.

Eksistensen af ​​irreversible hash-funktioner, for hvilke beregningen af ​​et hvilket som helst præbillede af en given hashværdi er teoretisk umulig, er ikke blevet bevist. Normalt er det kun en beregningsmæssigt vanskelig opgave at finde det gensidige.

Fødselsdagsangrebet giver dig mulighed for at finde kollisioner for en hashfunktion med værdier af længde n bit i gennemsnit over ca. hashfunktionsberegninger. Derfor betragtes en n -bit hash-funktion som sikker, hvis den beregningsmæssige kompleksitet ved at finde kollisioner for den er tæt på .

Kryptografiske hash-funktioner bør have en lavineeffekt - med den mindste ændring i argumentet ændres værdien af ​​funktionen meget. Især må hashværdien ikke lække information selv om individuelle bits af argumentet. Dette krav er nøglen til den kryptografiske styrke af hashing-algoritmer, der hash brugerens adgangskode for at få nøglen [8] .

Hashing bruges ofte i digitale signaturalgoritmer, hvor ikke selve beskeden er krypteret, men dens hash-kode, hvilket reducerer beregningstiden og øger den kryptografiske styrke. Også i de fleste tilfælde gemmes værdierne af deres hash-koder i stedet for adgangskoder.

Kontrolsummer

Checksum-beregningsalgoritmer er enkle, hurtige og let implementerbare hardwarealgoritmer, der bruges til at beskytte data mod utilsigtede forvrængninger, herunder hardwarefejl. Fra et matematisk synspunkt er sådanne algoritmer hash-funktioner, der beregner kontrolkoden. Kontrolkoden bruges til at opdage fejl, der kan opstå under transmission og lagring af information.

Algoritmer til beregning af kontrolsummer er titusinder og hundredvis af gange hurtigere end kryptografiske hash-funktioner og meget enklere i hardwareudførelse.

Prisen for en så høj hastighed er manglen på kryptografisk styrke - evnen til nemt at "passe" en besked til en forudkendt kontrolsum. Bitbredden af ​​kontrolsummer (typisk antal: 32 bit) er også normalt lavere end bitbredden af ​​kryptografiske hashes (typiske tal: 128, 160 og 256 bit), hvilket betyder, at utilsigtede kollisioner kan forekomme.

Den enkleste algoritme til at beregne kontrolsummen er at opdele beskeden (inputdata) i 32- eller 16-bit ord og derefter summere ordene. En sådan algoritme bruges for eksempel i TCP/IP-protokoller .

Som regel bør kontrolsumalgoritmer detektere typiske hardwarefejl, for eksempel bør de detektere flere på hinanden følgende bitfejl op til en given længde. Den såkaldte " cykliske redundanskode " familie af algoritmer opfylder disse krav. Disse inkluderer for eksempel CRC32- algoritmen, der bruges i Ethernet -enheder og i ZIP -datakomprimeringsformatet .

Kontrolsummen kan for eksempel sendes over kommunikationskanalen sammen med hovedteksten (data). I den modtagende ende kan kontrolsummen genberegnes og sammenlignes med den transmitterede værdi. Hvis der findes en uoverensstemmelse, er transmissionen blevet forvansket, og der kan anmodes om en gentransmission.

Et eksempel på brugen af ​​hash i hverdagen er at tælle antallet af kufferter med i bagagen. For at kontrollere sikkerheden af ​​kufferter er det ikke nødvendigt at kontrollere sikkerheden for hver kuffert, det er nok at tælle antallet af kufferter under lastning og losning. Matchende tal vil betyde, at ikke en eneste kuffert går tabt. Det vil sige, at antallet af kufferter er en hash-kode.

Denne metode kan suppleres for at beskytte overført information mod forfalskning ( MAC- metoden ). I dette tilfælde udføres hashing af en sikker funktion på beskeden kombineret med en hemmelig nøgle, der kun er kendt af afsenderen og modtageren af ​​beskeden. Kryptanalytikeren, der har opsnappet beskeden og værdien af ​​hashfunktionen, vil ikke være i stand til at gendanne koden, det vil sige, han vil ikke være i stand til at forfalske beskeden (se efterligningsbeskyttelse ).

Geometrisk hashing

Geometrisk hashing er en  metode, der er meget brugt i computergrafik og beregningsgeometri til at løse problemer på et plan eller i tredimensionelt rum, for eksempel for at finde de nærmeste par af punkter blandt et sæt punkter eller til at søge efter identiske billeder. Hash-funktionen i denne metode tager normalt noget metrisk rum som input og deler det op, hvilket skaber et gitter af celler. Hash-tabellen i dette tilfælde er et array med to eller flere indekser og kaldes en "grid-fil" ( engelsk grid-fil ). Geometrisk hashing bruges i telekommunikation, når man arbejder med multidimensionelle signaler [9] .  

Fremskynder datahentning

En hash-tabel er en datastruktur, der giver dig mulighed for at gemme par af formen "nøgle" - "hash-kode" og understøtter operationerne med at søge, indsætte og slette et element. Hash-tabeller bruges til at fremskynde opslag, for eksempel når tekstfelter skrives til en database, kan deres hash-kode beregnes, og dataene kan placeres i en sektion, der svarer til denne hash-kode. Derefter, når du søger efter data, vil det være nødvendigt først at beregne hash-koden for teksten, og det vil straks blive kendt, i hvilket afsnit de skal søges. Det vil sige, at det vil være nødvendigt at søge ikke i hele databasen, men kun i en af ​​dens sektioner, og det fremskynder søgningen.

I dette tilfælde kan den daglige analog af hashing være placeringen af ​​ord i ordbogen i alfabetisk rækkefølge. Det første bogstav i et ord er dets hash-kode, og ved søgning slås ikke hele ordbogen op, men kun ord, der begynder med det ønskede bogstav.

Noter

  1. Virt2, 2010 , s. 257.
  2. 1 2 Wirth, 1989 .
  3. Herbert Hellerman. Digitale computersystemprincipper. NY: McGraw-Hill, 1967, 424 s.
  4. 1 2 3 4 5 6 7 Knuth, 2007 .
  5. Pearson, Peter K. (juni 1990), Fast Hashing of Variable-Length Text Strings , Communications of the ACM vol . 33 (6): 677, doi : 10.1145/78973.78978 , < http://epaperpress.com/vbhash/ download/p677-pearson.pdf > 
  6. Djamal Belazzougui, Fabiano C. Botelho, Martin Dietzfelbinger. Hash, forskyd og komprimer  (neopr.) . — Springer Berlin / Heidelberg, 2009.
  7. Miltersen, Peter Bro Universal Hashing ( PDF). Arkiveret fra originalen den 24. juni 2009.  
  8. Schneier, 2002 .
  9. Wolfson, HJ & Rigoutsos, I (1997). Geometrisk hashing: en oversigt. IEEE Computational Science and Engineering, 4(4), 10-21.

Litteratur

  • Bruce Schneier . Anvendt kryptografi. Protokoller, algoritmer, kildetekster i C-sprog. - M . : Triumph, 2002. - ISBN 5-89392-055-4 .
  • Donald Knuth . Kunsten at programmere. Bind 3. Sortering og søgning = The Art of Computer Programming, vol.3. Sortering og søgning. — 2. udgave. - M . : " Williams ", 2007. - S. 824. - ISBN 0-201-89685-0 .
  • Niklaus Wirth . Algoritmer og datastrukturer. - M . : " Mir ", 1989. - ISBN 5-03-001045-9 .
  • Niklaus Wirth . Algoritmer og datastrukturer. Ny version til Oberon. - M . : "DMK Press", 2010. - ISBN 978-5-94074-584-6 .

Links