Denne veiledningen vil introdusere deg til hvordan du genererer sikre hashverdier ved hjelp av de innebygde funksjonene i Pythons `hashlib`-modul.
Å forstå viktigheten av hashing og hvordan man programmatisk beregner sikre hashverdier kan være nyttig, selv om du ikke primært jobber med applikasjonssikkerhet. Men hvorfor er dette viktig?
Når du arbeider med Python-prosjekter, vil du sannsynligvis støte på situasjoner der du trenger å være forsiktig med lagring av passord og annen sensitiv data i databaser eller kildekodefiler. I slike tilfeller er det tryggere å bruke en hashing-algoritme på den sensitive informasjonen og lagre hashverdien i stedet for selve informasjonen.
I denne veiledningen skal vi se på hva hashing er og hvordan det skiller seg fra kryptering. Vi vil også diskutere egenskapene til sikre hashfunksjoner. Deretter skal vi bruke vanlige hashing-algoritmer for å beregne hashverdien til ren tekst i Python. Vi skal gjøre dette ved å bruke den innebygde `hashlib`-modulen.
Så, la oss komme i gang!
Hva er hashing?
Hashing er en prosess der en melding eller tekststreng konverteres til en utdata med en fast lengde som kalles en hash. Dette betyr at lengden på hashverdien er konstant, uavhengig av lengden på inndata, for en gitt hashing-algoritme. Men hvordan er dette forskjellig fra kryptering?
Kryptering innebærer at en melding eller klartekst krypteres ved hjelp av en krypteringsalgoritme, noe som resulterer i en kryptert utdata. Denne krypterte utdataen kan deretter dekrypteres for å få tilbake den opprinnelige meldingen.
Hashing fungerer imidlertid annerledes. Krypteringsprosessen er reversibel, noe som betyr at du kan konvertere fra den krypterte meldingen til den ukrypterte meldingen og vice versa.
I motsetning til kryptering er hashing en enveisprosess, noe som betyr at det er umulig å konvertere fra hashverdien tilbake til den opprinnelige inndataen.
Egenskaper ved hashfunksjoner
La oss gå raskt gjennom noen av egenskapene som hashfunksjoner bør oppfylle:
- Deterministisk: Hashfunksjoner er deterministiske. Gitt en melding `m`, vil hashverdien av `m` alltid være den samme.
- Preimage-resistent: Dette har vi allerede dekket ved å si at hashing ikke er en reversibel operasjon. Preimage-resistens betyr at det er umulig å finne meldingen `m` fra utdata-hashverdien.
- Kollisjonsresistent: Det skal være vanskelig, eller til og med umulig, å finne to forskjellige meldinger `m1` og `m2` slik at hashverdien av `m1` er lik hashverdien av `m2`. Denne egenskapen kalles kollisjonsresistens.
- Second Preimage-resistent: Dette betyr at gitt en melding `m1` og den tilsvarende hashverdien, er det umulig å finne en annen melding `m2` slik at hash(m1) = hash(m2).
Pythons `hashlib`-modul
Pythons innebygde `hashlib`-modul tilbyr implementasjoner av flere hashing- og meldingsoppsummeringsalgoritmer, inkludert SHA- og MD5-algoritmene.
For å bruke konstruktørene og de innebygde funksjonene fra `hashlib`-modulen, kan du importere den til arbeidsmiljøet ditt på følgende måte:
import hashlib
`hashlib`-modulen gir konstantene `algorithms_available` og `algorithms_guaranteed`, som representerer settene av algoritmer som er tilgjengelige og som er garantert på en plattform, henholdsvis.
Derfor er `algorithms_guaranteed` en delmengde av `algorithms_available`.
Start en Python REPL, importer `hashlib` og få tilgang til konstantene `algorithms_available` og `algorithms_guaranteed`:
>>> hashlib.algorithms_available
# Utdata {'md5', 'md5-sha1', 'sha3_256', 'shake_128', 'sha384', 'sha512_256', 'sha512', 'md4', 'shake_256', 'whirlpool', 'sha1', 'sha3_512', 'sha3_384', 'sha256', 'ripemd160', 'mdc2', 'sha512_224', 'blake2s', 'blake2b', 'sha3_224', 'sm3', 'sha224'}
>>> hashlib.algorithms_guaranteed
# Utdata {'md5', 'shake_256', 'sha3_256', 'shake_128', 'blake2b', 'sha3_224', 'sha3_384', 'sha384', 'sha256', 'sha1', 'sha3_512', 'sha512', 'blake2s', 'sha224'}
Vi ser at `algorithms_guaranteed` faktisk er en undergruppe av `algorithms_available`.
Hvordan lage hashobjekter i Python
La oss nå lære hvordan du lager hashobjekter i Python. Vi skal beregne SHA256-hashverdien for en meldingsstreng ved å bruke følgende metoder:
- Den generiske `new()`-konstruktøren
- Algoritmespesifikke konstruktører
Bruke `new()`-konstruktøren
La oss initialisere en meldingsstreng:
>>> message = "tipsbilk.net is awesome!"
For å instansiere hashobjektet, kan vi bruke `new()`-konstruktøren og angi navnet på algoritmen slik:
>>> sha256_hash = hashlib.new("SHA256")
Vi kan nå kalle `update()`-metoden på hashobjektet med meldingsstrengen som argument:
>>> sha256_hash.update(message)
Hvis du gjør dette, vil du få en feilmelding fordi hashing-algoritmer bare fungerer med byte-strenger.
Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Unicode-objects must be encoded before hashing
For å få den kodede strengen, kan du kalle `encode()`-metoden på strengen og deretter bruke den i `update()`-metodekallet. Etter å ha gjort det, kan du kalle `hexdigest()`-metoden for å få SHA256-hashverdien som tilsvarer meldingsstrengen.
sha256_hash.update(message.encode()) sha256_hash.hexdigest() # Utdata: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
I stedet for å kode meldingsstrengen ved hjelp av `encode()`-metoden, kan du også definere den som en byte-streng ved å prefikse strengen med `b` som dette:
message = b"tipsbilk.net is awesome!" sha256_hash.update(message) sha256_hash.hexdigest() # Utdata: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
Den oppnådde hashverdien er den samme som den forrige, noe som bekrefter den deterministiske egenskapen til hashfunksjoner.
I tillegg vil en liten endring i meldingsstrengen føre til at hashverdien endres drastisk (også kjent som «skred-effekt»).
For å bekrefte dette, la oss endre `a` i `awesome` til `A` og beregne hashverdien:
message = "tipsbilk.net is Awesome!" h1 = hashlib.new("SHA256") h1.update(message.encode()) h1.hexdigest() # Utdata: '3c67f334cc598912dc66464f77acb71d88cfd6c8cba8e64a7b749d093c1a53ab'
Vi ser at hashverdien endres fullstendig.
Bruke den algoritmespesifikke konstruktøren
I det forrige eksemplet brukte vi den generiske `new()`-konstruktøren og ga `»SHA256″` som navnet på algoritmen for å lage hashobjektet.
I stedet for å gjøre dette, kan vi også bruke `sha256()`-konstruktøren som vist:
sha256_hash = hashlib.sha256() message= "tipsbilk.net is awesome!" sha256_hash.update(message.encode()) sha256_hash.hexdigest() # Utdata: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
Utdatahashverdien er identisk med hashverdien vi fikk tidligere for meldingsstrengen `»tipsbilk.net is awesome!»`.
Utforske attributtene til hashobjekter
Hashobjekter har noen nyttige attributter:
- `digest_size`-attributtet angir størrelsen på sammendraget i byte. For eksempel returnerer SHA256-algoritmen en 256-bits hash, som tilsvarer 32 byte.
- `block_size`-attributtet refererer til blokkstørrelsen som brukes i hashing-algoritmen.
- `name`-attributtet er navnet på algoritmen som vi kan bruke i `new()`-konstruktøren. Det kan være nyttig å se opp verdien av dette attributtet når hashobjektene ikke har beskrivende navn.
Vi kan sjekke disse attributtene for `sha256_hash`-objektet vi opprettet tidligere:
>>> sha256_hash.digest_size 32 >>> sha256_hash.block_size 64 >>> sha256_hash.name 'sha256'
La oss se på noen interessante bruksområder for hashing ved hjelp av Pythons `hashlib`-modul.
Praktiske eksempler på hashing
Verifisere integriteten til programvare og filer
Som utviklere laster vi ned og installerer programvarepakker hele tiden. Dette gjelder enten du jobber på en Linux-distro, Windows eller Mac.
Det kan imidlertid hende at noen speil for programvarepakker ikke er pålitelige. Du kan finne hashverdien (eller sjekksummen) ved siden av nedlastingslenken. Og du kan verifisere integriteten til den nedlastede programvaren ved å beregne hashverdien og sammenligne den med den offisielle hashverdien.
Dette kan også brukes på filer på maskinen din. Selv den minste endring i filinnholdet vil drastisk endre hashverdien. Du kan sjekke om en fil har blitt endret ved å verifisere hashverdien.
Her er et enkelt eksempel. Lag en tekstfil `my_file.txt` i arbeidskatalogen, og legg til litt innhold i den.
$ cat my_file.txt This is a sample text file. We are going to compute the SHA256 hash of this text file and also check if the file has been modified by recomputing the hash.
Du kan deretter åpne filen i binærlesemodus (`»rb»`), lese inn innholdet i filen og beregne SHA256-hashverdien som vist:
>>> import hashlib >>> with open("my_file.txt","rb") as file: ... file_contents = file.read() ... sha256_hash = hashlib.sha256() ... sha256_hash.update(file_contents) ... original_hash = sha256_hash.hexdigest()
Her inneholder variabelen `original_hash` hashverdien for `my_file.txt` i sin nåværende tilstand.
>>> original_hash # Utdata: '53bfd0551dc06c4515069d1f0dc715d002d451c8799add29f3e5b7328fda9f8f'
Endre nå filen `my_file.txt`. Du kan for eksempel fjerne det ekstra innledende mellomrommet før ordet `»going»`. 🙂
Beregn hashverdien på nytt og lagre den i variabelen `computed_hash`.
>>> import hashlib >>> with open("my_file.txt","rb") as file: ... file_contents = file.read() ... sha256_hash = hashlib.sha256() ... sha256_hash.update(file_contents) ... computed_hash = sha256_hash.hexdigest()
Du kan deretter legge til en enkel `assert`-setning som sjekker om `computed_hash` er lik `original_hash`.
>>> assert computed_hash == original_hash
Hvis filen er endret (som er tilfellet her), bør du få en `AssertionError`:
Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError
Du kan bruke hashing når du lagrer sensitiv informasjon, som passord i databaser. Du kan også bruke hashing i passordautentisering når du kobler til databaser. Bekreft hashverdien for det angitte passordet mot hashverdien for det riktige passordet.
Konklusjon
Jeg håper denne veiledningen har hjulpet deg med å lære om generering av sikre hashverdier med Python. Her er de viktigste punktene:
- Pythons `hashlib`-modul tilbyr ferdige implementasjoner av flere hashing-algoritmer. Du kan få listen over garanterte algoritmer på plattformen din ved å bruke `hashlib.algorithms_guaranteed`.
- For å lage et hashobjekt kan du bruke den generiske `new()`-konstruktøren med syntaksen: `hashlib.new(«algo-name»)`. Alternativt kan du bruke konstruktørene som tilsvarer de spesifikke hashing-algoritmene, som `hashlib.sha256()` for SHA256-hashverdien.
- Etter å ha initialisert meldingsstrengen som skal hashes og hashobjektet, kan du kalle `update()`-metoden på hashobjektet, etterfulgt av `hexdigest()`-metoden for å få hashverdien.
- Hashing kan være nyttig når du sjekker integriteten til programvare og filer, lagrer sensitiv informasjon i databaser og mer.
Neste skritt er å lære hvordan du koder en tilfeldig passordgenerator i Python.