Biztonságos kivonatolás a Python Hashlib segítségével

Ez az oktatóanyag megtanítja Önnek, hogyan hozhat létre biztonságos kivonatokat a Python hashlib moduljának beépített funkcióival.

Hasznos lehet megérteni a kivonatolás jelentőségét és a biztonságos kivonatok programozott kiszámítását – még akkor is, ha nem dolgozik az alkalmazásbiztonsággal. De miért?

Nos, amikor Python-projekteken dolgozik, valószínűleg találkozni fog olyan esetekkel, amikor aggódik a jelszavak és más érzékeny információk adatbázisokban vagy forráskódfájlokban való tárolása miatt. Ilyen esetekben biztonságosabb, ha kényes információkon futtatja a kivonatolási algoritmust, és az információ helyett a hash-t tárolja.

Ebben az útmutatóban bemutatjuk, mi az a hash, és miben különbözik a titkosítástól. A biztonságos hash függvények tulajdonságait is áttekintjük. Ezután általános kivonatolási algoritmusokat használunk a Pythonban lévő egyszerű szöveg kivonatának kiszámításához. Ehhez a beépített hashlib modult fogjuk használni.

Mindehhez és még sok máshoz kezdjük!

Mi az a kivonatolás?

A kivonatolási folyamat egy üzenet karakterláncot vesz fel, és egy rögzített hosszúságú kimenetet ad, amelyet hash-nek neveznek. Ez azt jelenti, hogy a kimeneti hash hossza egy adott kivonatolási algoritmushoz rögzített – függetlenül a bemenet hosszától. De miben különbözik a titkosítástól?

A titkosítás során az üzenetet vagy az egyszerű szöveget egy titkosítási algoritmussal titkosítják, amely titkosított kimenetet ad. Ezután lefuttathatjuk a visszafejtési algoritmust a titkosított kimeneten, hogy visszakapjuk az üzenetet.

A hashelés azonban másként működik. Most tanultuk meg, hogy a titkosítási folyamat megfordítható, mivel a titkosított üzenetről át lehet lépni a titkosítatlan üzenetre, és fordítva.

A titkosítással ellentétben a kivonatolás nem invertálható folyamat, ami azt jelenti, hogy nem tudunk a hash-től a bemeneti üzenetig eljutni.

A hash-függvények tulajdonságai

Nézzünk meg gyorsan néhány olyan tulajdonságot, amelyeknek a hash függvényeknek eleget kell tenniük:

  • Determinisztikus: A hash függvények determinisztikusak. Egy m üzenet esetén m hash értéke mindig ugyanaz.
  • Preimage Resistant: Már foglalkoztunk ezzel, amikor azt mondtuk, hogy a hash nem invertálható művelet. Az előkép ellenállás tulajdonsága azt állítja, hogy lehetetlen megtalálni az m üzenetet a kimeneti hash-ből.
  • Ütközésálló: Nehéznek (vagy számításilag kivitelezhetetlennek) kell lennie két különböző m1 és m2 üzenetsor megtalálása úgy, hogy az m1 hashje egyenlő legyen az m2 hash-ével. Ezt a tulajdonságot ütközésállóságnak nevezzük.
  • Második Preimage Resistant: Ez azt jelenti, hogy adott egy m1 üzenet és a megfelelő m2 hash, nem lehetséges olyan m2 üzenetet találni, amelynél hash(m1) = hash(m2).
  15 nagyszerű Mac OS X terminálparancs, amelyet esetleg nem ismer

Python hashlib modulja

A Python beépített hashlib modulja számos kivonatolási és üzenetkivonat-algoritmus megvalósítását biztosítja, beleértve az SHA és MD5 algoritmusokat.

A Python hashlib modul konstruktorainak és beépített függvényeinek használatához importálhatja azt a munkakörnyezetébe, így:

import hashlib

A hashlib modul biztosítja az algorithms_available és algorithms_guaranteed konstansokat, amelyek az algoritmusok azon halmazát jelölik, amelyek megvalósítása elérhető és garantált egy platformon.

Ezért az algoritmusok_garantált az algorithms_available részhalmaza.

Indítson el egy Python REPL-t, importálja a hashlib-et, és érje el az algorithms_available és algorithms_guaranteed konstansokat:

>>> hashlib.algorithms_available
# Output
{'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
# Output
{'md5', 'shake_256', 'sha3_256', 'shake_128', 'blake2b', 'sha3_224', 'sha3_384', 
'sha384', 'sha256', 'sha1', 'sha3_512', 'sha512', 'blake2s', 'sha224'}

Látjuk, hogy az algoritmusok_garantált valóban az algorithms_available részhalmaza

Hogyan lehet Hash objektumokat létrehozni Pythonban

Ezután tanuljuk meg, hogyan hozhat létre hash objektumokat Pythonban. Kiszámítjuk egy üzenetkarakterlánc SHA256 hash értékét a következő módszerekkel:

  • Az általános new() konstruktor
  • Algoritmus-specifikus konstruktorok

A new() konstruktor használatával

Inicializáljuk az üzenetet:

>>> message = "etoppc.com is awesome!"

A hash objektum példányosításához használhatjuk a new() konstruktort, és átadhatjuk az algoritmus nevét, amint látható:

>>> sha256_hash = hashlib.new("SHA256")

Most már meghívhatjuk az update() metódust a hash objektumon az üzenet karakterlánccal argumentumként:

>>> sha256_hash.update(message)

Ha így tesz, hibába ütközik, mivel a kivonatoló algoritmusok csak bájtkarakterláncokkal működnek.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Unicode-objects must be encoded before hashing

A kódolt karakterlánc beszerzéséhez hívja meg az encode() metódust a metódusban, majd használja az update() metódushívásban. Ezt követően meghívhatja a hexdigest() metódust, hogy megkapja az üzenet karakterláncának megfelelő sha256 hash-t.

sha256_hash.update(message.encode())
sha256_hash.hexdigest()
# Output:'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'

Ahelyett, hogy az üzenetet az encode() metódussal kódolná, bájtok karakterláncaként is megadhatja, ha a karakterláncot b előtaggal rögzíti, így:

message = b"etoppc.com is awesome!"
sha256_hash.update(message)
sha256_hash.hexdigest()
# Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'

A kapott hash ugyanaz, mint az előző hash, ami megerősíti a hash függvények determinisztikus jellegét.

  Javítás Nem lehet elindítani a programot, a Visual Studio hozzáférése megtagadva

Ezen túlmenően, egy kis változtatás az üzenetkarakterláncban a hash drasztikus változását okozhatja (más néven „lavinaeffektus”).

Ennek ellenőrzésére változtassuk az „a”-t az „awesome”-ban „A”-ra, és számítsuk ki a hash-t:

message = "etoppc.com is Awesome!"
h1 = hashlib.new("SHA256")
h1.update(message.encode())
h1.hexdigest()
# Output: '3c67f334cc598912dc66464f77acb71d88cfd6c8cba8e64a7b749d093c1a53ab'

Látjuk, hogy a hash teljesen megváltozik.

Az algoritmus-specifikus konstruktor használata

Az előző példában az általános new() konstruktort használtuk, és az „SHA256”-ot adtuk meg az algoritmus neveként a hash objektum létrehozásához.

Ehelyett használhatjuk az sha256() konstruktort is, ahogy az ábra mutatja:

sha256_hash = hashlib.sha256()
message= "etoppc.com is awesome!"
sha256_hash.update(message.encode())
sha256_hash.hexdigest()
# Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'

A kimeneti hash megegyezik azzal a hashvel, amelyet korábban a „etoppc.com is awesome!” üzenethez kaptunk.

A hash-objektumok attribútumainak feltárása

A hash objektumok néhány hasznos tulajdonsággal rendelkeznek:

  • Az digest_size attribútum a kivonat méretét jelöli bájtokban. Például az SHA256 algoritmus 256 bites hash-t ad vissza, ami 32 bájtnak felel meg.
  • A block_size attribútum a kivonatolási algoritmusban használt blokkméretre vonatkozik.
  • A name attribútum annak az algoritmusnak a neve, amelyet a new() konstruktorban használhatunk. Az attribútum értékének megkeresése hasznos lehet, ha a hash objektumoknak nincs leíró neve.

Ezeket az attribútumokat ellenőrizhetjük a korábban létrehozott sha256_hash objektumhoz:

>>> sha256_hash.digest_size
32
>>> sha256_hash.block_size
64
>>> sha256_hash.name
'sha256'

Ezután nézzünk meg néhány érdekes hash-alkalmazást a Python hashlib moduljával.

Gyakorlati példák a kivonatolásra

Szoftverek és fájlok integritásának ellenőrzése

Fejlesztőként folyamatosan letöltünk és telepítünk szoftvercsomagokat. Ez attól függetlenül igaz, hogy Linux disztribúción, Windowson vagy Macen dolgozik.

Előfordulhat azonban, hogy a szoftvercsomagokhoz tartozó egyes tükrök nem megbízhatóak. A hash (vagy ellenőrző összeg) a letöltési link mellett található. A letöltött szoftver integritását pedig úgy ellenőrizheti, hogy kiszámítja a hash-t, és összehasonlítja a hivatalos hash-sel.

  Ezzel a 3 sablonnal térképezze fel alkalmazotti tapasztalatait és utazásait

Ez a gépén lévő fájlokra is alkalmazható. Még a legkisebb változtatás is a fájl tartalmában drasztikusan megváltoztatja a hash-t, a hash ellenőrzésével ellenőrizheti, hogy a fájl módosult-e.

Íme egy egyszerű példa. Hozzon létre egy „sajat_fájl.txt” szövegfájlt a munkakönyvtárban, és adjon hozzá tartalmat.

$ 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.

Ezután megnyithatja a fájlt olvasási bináris módban (‘rb’), beolvashatja a fájl tartalmát, és kiszámíthatja az SHA256 hash-t a képen látható módon:

>>> 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()

Itt az original_hash változó a ‘my_file.txt’ kivonata jelenlegi állapotában.

>>> original_hash
# Output: '53bfd0551dc06c4515069d1f0dc715d002d451c8799add29f3e5b7328fda9f8f'

Most módosítsa a ‘my_file.txt’ fájlt. Eltávolíthatja az extra szóközt a „megy” szó előtt. 🙂

Számítsa ki még egyszer a hash-t, és tárolja a computed_hash változóban.

>>> 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()

Ezután hozzáadhat egy egyszerű assert utasítást, amely azt állítja, hogy a computed_hash egyenlő az eredeti_kivonattal.

>>> assert computed_hash == original_hash

Ha a fájl módosul (ez ebben az esetben igaz), AssertionError üzenetet kell kapnia:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

A kivonatolást kényes adatok, például jelszavak adatbázisokban való tárolásakor használhatja. Adatbázisokhoz való csatlakozáskor a jelszó-hitelesítés során is használhatja a hash-t. Érvényesítse a bevitt jelszó kivonatát a helyes jelszó kivonatával.

Következtetés

Remélem, ez az oktatóanyag segített megtanulni a biztonságos kivonatok létrehozását a Python segítségével. Íme a legfontosabb tudnivalók:

  • A Python hashlib modulja számos kivonatolási algoritmus használatra kész megvalósítását biztosítja. A platformján garantált algoritmusok listáját a hashlib.algorithms_guaranteed segítségével érheti el.
  • Hash objektum létrehozásához használhatja az általános new() konstruktort a következő szintaxissal: hashlib.new(“algo-name”). Alternatív megoldásként használhatja az adott kivonatolási algoritmusoknak megfelelő konstruktorokat, például: hashlib.sha256() az SHA 256 hash-hez.
  • A kivonatolni kívánt üzenetkarakterlánc és a hash objektum inicializálása után meghívhatja az update() metódust a hash objektumon, majd a hexdigest() metódust a hash lekéréséhez.
  • A kivonatolás hasznos lehet a szoftveres műtermékek és fájlok integritásának ellenőrzésekor, érzékeny információk adatbázisokban való tárolásakor stb.

Ezután tanulja meg, hogyan kell kódolni egy véletlenszerű jelszógenerátort Pythonban.