Ασφαλής κατακερματισμός με Python Hashlib

Αυτό το σεμινάριο θα σας διδάξει πώς να δημιουργείτε ασφαλή hashes χρησιμοποιώντας ενσωματωμένη λειτουργικότητα από τη λειτουργική μονάδα hashlib της Python.

Η κατανόηση της σημασίας του κατακερματισμού και του τρόπου υπολογισμού των ασφαλών κατακερματισμών μέσω προγραμματισμού μπορεί να είναι χρήσιμη — ακόμα κι αν δεν εργάζεστε σε θέματα ασφάλειας εφαρμογών. Μα γιατί?

Λοιπόν, όταν εργάζεστε σε έργα Python, πιθανότατα θα συναντήσετε περιπτώσεις όπου ανησυχείτε για την αποθήκευση κωδικών πρόσβασης και άλλων ευαίσθητων πληροφοριών σε βάσεις δεδομένων ή αρχεία πηγαίου κώδικα. Σε τέτοιες περιπτώσεις, είναι ασφαλέστερο να εκτελείτε τον αλγόριθμο κατακερματισμού σε ευαίσθητες πληροφορίες και να αποθηκεύετε τον κατακερματισμό αντί για τις πληροφορίες.

Σε αυτόν τον οδηγό, θα καλύψουμε τι είναι ο κατακερματισμός και πώς διαφέρει από την κρυπτογράφηση. Θα εξετάσουμε επίσης τις ιδιότητες των συναρτήσεων ασφαλούς κατακερματισμού. Στη συνέχεια, θα χρησιμοποιήσουμε κοινούς αλγόριθμους κατακερματισμού για να υπολογίσουμε τον κατακερματισμό του απλού κειμένου στην Python. Για να το κάνουμε αυτό, θα χρησιμοποιήσουμε την ενσωματωμένη ενότητα hashlib.

Για όλα αυτά και πολλά άλλα, ας ξεκινήσουμε!

Τι είναι το Hashing;

Η διαδικασία κατακερματισμού λαμβάνει μια συμβολοσειρά μηνύματος και δίνει μια έξοδο σταθερού μήκους που ονομάζεται κατακερματισμός. Αυτό σημαίνει ότι το μήκος του κατακερματισμού εξόδου για έναν δεδομένο αλγόριθμο κατακερματισμού είναι σταθερό – ανεξάρτητα από το μήκος της εισόδου. Αλλά σε τι διαφέρει από την κρυπτογράφηση;

Στην κρυπτογράφηση, το μήνυμα ή το απλό κείμενο κρυπτογραφείται χρησιμοποιώντας έναν αλγόριθμο κρυπτογράφησης που δίνει μια κρυπτογραφημένη έξοδο. Στη συνέχεια, μπορούμε να εκτελέσουμε τον αλγόριθμο αποκρυπτογράφησης στην κρυπτογραφημένη έξοδο για να ανακτήσουμε τη συμβολοσειρά μηνύματος.

Ωστόσο, ο κατακερματισμός λειτουργεί διαφορετικά. Μόλις μάθαμε ότι η διαδικασία της κρυπτογράφησης είναι αναστρέψιμη στο ότι μπορείτε να μεταβείτε από το κρυπτογραφημένο μήνυμα στο μη κρυπτογραφημένο μήνυμα και το αντίστροφο.

Σε αντίθεση με την κρυπτογράφηση, ο κατακερματισμός δεν είναι μια αναστρέψιμη διαδικασία, που σημαίνει ότι δεν μπορούμε να μεταβούμε από τον κατακερματισμό στο μήνυμα εισαγωγής.

Ιδιότητες των συναρτήσεων κατακερματισμού

Ας δούμε γρήγορα ορισμένες ιδιότητες που πρέπει να ικανοποιούν οι συναρτήσεις κατακερματισμού:

  • Ντετερμινιστικό: Οι συναρτήσεις κατακερματισμού είναι ντετερμινιστικές. Με δεδομένο ένα μήνυμα m, ο κατακερματισμός του m είναι πάντα ο ίδιος.
  • Preimage Resistant: Το έχουμε ήδη καλύψει όταν είπαμε ότι ο κατακερματισμός δεν είναι μια αντιστρέψιμη λειτουργία. Η ιδιότητα αντίστασης προεικόνας δηλώνει ότι δεν είναι εφικτό να βρεθεί το μήνυμα m από τον κατακερματισμό εξόδου.
  • Ανθεκτικό σε σύγκρουση: Θα πρέπει να είναι δύσκολο (ή υπολογιστικά ανέφικτο) να βρεθούν δύο διαφορετικές συμβολοσειρές μηνυμάτων m1 και m2 έτσι ώστε ο κατακερματισμός του m1 να είναι ίσος με τον κατακερματισμό του m2. Αυτή η ιδιότητα ονομάζεται αντίσταση σύγκρουσης.
  • Δεύτερο Preimage Resistant: Αυτό σημαίνει ότι δεδομένου ενός μηνύματος m1 και του αντίστοιχου hash m2, δεν είναι εφικτό να βρεθεί ένα άλλο μήνυμα m2 έτσι ώστε hash(m1) = hash(m2).
  Πώς να βρείτε την πραγματική διεύθυνση IP (Προέλευση) του ιστότοπου;

Ενότητα hashlib της Python

Η ενσωματωμένη μονάδα hashlib της Python παρέχει υλοποιήσεις αρκετών αλγορίθμων κατακερματισμού και σύνοψης μηνυμάτων, συμπεριλαμβανομένων των αλγορίθμων SHA και MD5.

Για να χρησιμοποιήσετε τους κατασκευαστές και τις ενσωματωμένες συναρτήσεις από τη λειτουργική μονάδα hashlib της Python, μπορείτε να την εισαγάγετε στο περιβάλλον εργασίας σας ως εξής:

import hashlib

Η ενότητα hashlib παρέχει τις σταθερές algorithms_available και algorithms_guaranteed, οι οποίες υποδηλώνουν το σύνολο των αλγορίθμων των οποίων οι υλοποιήσεις είναι διαθέσιμες και είναι εγγυημένες σε μια πλατφόρμα, αντίστοιχα.

Επομένως, το algorithms_guaranteed είναι ένα υποσύνολο των algorithms_available.

Ξεκινήστε μια Python REPL, εισαγάγετε hashlib και αποκτήστε πρόσβαση στις σταθερές algorithms_available και algorithms_guaranteed:

>>> 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'}

Βλέπουμε ότι το algorithms_guaranteed είναι πράγματι ένα υποσύνολο των algorithms_available

Πώς να δημιουργήσετε αντικείμενα Hash στην Python

Στη συνέχεια, ας μάθουμε πώς να δημιουργήσουμε αντικείμενα κατακερματισμού στην Python. Θα υπολογίσουμε τον κατακερματισμό SHA256 μιας συμβολοσειράς μηνύματος χρησιμοποιώντας τις ακόλουθες μεθόδους:

  • Ο γενικός κατασκευαστής new().
  • Κατασκευαστές ειδικών αλγορίθμων

Χρησιμοποιώντας τον κατασκευαστή new().

Ας αρχικοποιήσουμε τη συμβολοσειρά μηνύματος:

>>> message = "grtechpc.org is awesome!"

Για να δημιουργήσουμε το αντικείμενο κατακερματισμού, μπορούμε να χρησιμοποιήσουμε τον κατασκευαστή new() και να περάσουμε στο όνομα του αλγορίθμου όπως φαίνεται:

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

Μπορούμε τώρα να καλέσουμε τη μέθοδο update() στο αντικείμενο κατακερματισμού με τη συμβολοσειρά μηνύματος ως όρισμα:

>>> sha256_hash.update(message)

Εάν το κάνετε, θα αντιμετωπίσετε ένα σφάλμα, καθώς οι αλγόριθμοι κατακερματισμού μπορούν να λειτουργήσουν μόνο με συμβολοσειρές byte.

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

Για να λάβετε την κωδικοποιημένη συμβολοσειρά, μπορείτε να καλέσετε τη μέθοδο encode() στη συμβολοσειρά της μεθόδου και στη συνέχεια να τη χρησιμοποιήσετε στην κλήση της μεθόδου update(). Αφού το κάνετε αυτό, μπορείτε να καλέσετε τη μέθοδο hexdigest() για να λάβετε τον κατακερματισμό sha256 που αντιστοιχεί στη συμβολοσειρά μηνύματος.

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

Αντί να κωδικοποιήσετε τη συμβολοσειρά του μηνύματος χρησιμοποιώντας τη μέθοδο encode(), μπορείτε επίσης να την ορίσετε ως μια συμβολοσειρά byte βάζοντας το πρόθεμα της συμβολοσειράς με το b όπως:

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

Ο κατακερματισμός που προκύπτει είναι ο ίδιος με τον προηγούμενο κατακερματισμό, γεγονός που επιβεβαιώνει την ντετερμινιστική φύση των συναρτήσεων κατακερματισμού.

  6 Το καλύτερο λογισμικό οινοποιείου για να διαχειριστείτε τη συλλογή σας

Επιπλέον, μια μικρή αλλαγή στη συμβολοσειρά μηνύματος θα πρέπει να προκαλέσει δραστική αλλαγή του κατακερματισμού (γνωστό και ως “φαινόμενο χιονοστιβάδας”).

Για να το επαληθεύσουμε, ας αλλάξουμε το “a” στο “wesome” σε “A” και ας υπολογίσουμε τον κατακερματισμό:

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

Βλέπουμε ότι ο κατακερματισμός αλλάζει εντελώς.

Χρησιμοποιώντας τον κατασκευαστή για συγκεκριμένο αλγόριθμο

Στο προηγούμενο παράδειγμα, χρησιμοποιήσαμε τον γενικό κατασκευαστή new() και περάσαμε στο “SHA256” ως το όνομα του αλγορίθμου για τη δημιουργία του αντικειμένου κατακερματισμού.

Αντί να το κάνουμε αυτό, μπορούμε επίσης να χρησιμοποιήσουμε τον κατασκευαστή sha256() όπως φαίνεται:

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

Ο κατακερματισμός εξόδου είναι πανομοιότυπος με τον κατακερματισμό που λάβαμε νωρίτερα για τη συμβολοσειρά μηνύματος “grtechpc.org είναι φοβερό!”.

Εξερευνώντας τις ιδιότητες των αντικειμένων κατακερματισμού

Τα αντικείμενα κατακερματισμού έχουν μερικά χρήσιμα χαρακτηριστικά:

  • Το χαρακτηριστικό digest_size υποδηλώνει το μέγεθος της σύνοψης σε byte. Για παράδειγμα, ο αλγόριθμος SHA256 επιστρέφει έναν κατακερματισμό 256-bit, που ισοδυναμεί με 32 byte
  • Το χαρακτηριστικό block_size αναφέρεται στο μέγεθος του μπλοκ που χρησιμοποιείται στον αλγόριθμο κατακερματισμού.
  • Το χαρακτηριστικό name είναι το όνομα του αλγορίθμου που μπορούμε να χρησιμοποιήσουμε στον κατασκευαστή new(). Η αναζήτηση της τιμής αυτού του χαρακτηριστικού μπορεί να είναι χρήσιμη όταν τα αντικείμενα κατακερματισμού δεν έχουν περιγραφικά ονόματα.

Μπορούμε να ελέγξουμε αυτά τα χαρακτηριστικά για το αντικείμενο sha256_hash που δημιουργήσαμε νωρίτερα:

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

Στη συνέχεια, ας δούμε μερικές ενδιαφέρουσες εφαρμογές κατακερματισμού χρησιμοποιώντας τη μονάδα hashlib της Python.

Πρακτικά παραδείγματα κατακερματισμού

Επαλήθευση της ακεραιότητας του λογισμικού και των αρχείων

Ως προγραμματιστές, κατεβάζουμε και εγκαθιστούμε πακέτα λογισμικού συνεχώς. Αυτό ισχύει ανεξάρτητα από το αν εργάζεστε στη διανομή Linux ή σε Windows ή Mac.

Ωστόσο, ορισμένοι καθρέφτες για πακέτα λογισμικού μπορεί να μην είναι αξιόπιστοι. Μπορείτε να βρείτε τον κατακερματισμό (ή το άθροισμα ελέγχου) δίπλα στον σύνδεσμο λήψης. Και μπορείτε να επαληθεύσετε την ακεραιότητα του ληφθέντος λογισμικού υπολογίζοντας τον κατακερματισμό και συγκρίνοντάς το με τον επίσημο κατακερματισμό.

  Μάθετε πώς να χρησιμοποιείτε τη Διαχείριση εργασιών σε Mac

Αυτό μπορεί να εφαρμοστεί και σε αρχεία στο μηχάνημά σας. Ακόμη και η παραμικρή αλλαγή στα περιεχόμενα του αρχείου θα αλλάξει δραστικά τον κατακερματισμό, μπορείτε να ελέγξετε εάν ένα αρχείο έχει τροποποιηθεί επαληθεύοντας τον κατακερματισμό.

Εδώ είναι ένα απλό παράδειγμα. Δημιουργήστε ένα αρχείο κειμένου “my_file.txt” στον κατάλογο εργασίας και προσθέστε κάποιο περιεχόμενο σε αυτό.

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

Στη συνέχεια, μπορείτε να ανοίξετε το αρχείο σε λειτουργία ανάγνωσης δυαδικής λειτουργίας (‘rb’), να διαβάσετε τα περιεχόμενα του αρχείου και να υπολογίσετε τον κατακερματισμό SHA256 όπως φαίνεται:

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

Εδώ, η μεταβλητή original_hash είναι ο κατακερματισμός του ‘my_file.txt’ στην τρέχουσα κατάστασή του.

>>> original_hash
# Output: '53bfd0551dc06c4515069d1f0dc715d002d451c8799add29f3e5b7328fda9f8f'

Τώρα τροποποιήστε το αρχείο ‘my_file.txt’. Μπορείτε να αφαιρέσετε το επιπλέον κενό διάστημα πριν από τη λέξη “going”. 🙂

Υπολογίστε ξανά τον κατακερματισμό και αποθηκεύστε τον στη μεταβλητή 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()

Στη συνέχεια, μπορείτε να προσθέσετε μια απλή δήλωση ισχυρισμού που βεβαιώνει εάν το computed_hash είναι ίσο με το original_hash.

>>> assert computed_hash == original_hash

Εάν το αρχείο τροποποιηθεί (κάτι που ισχύει σε αυτήν την περίπτωση), θα πρέπει να λάβετε ένα AssertionError:

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

Μπορείτε να χρησιμοποιήσετε κατακερματισμό κατά την αποθήκευση ευαίσθητων πληροφοριών, όπως κωδικούς πρόσβασης σε βάσεις δεδομένων. Μπορείτε επίσης να χρησιμοποιήσετε κατακερματισμό στον έλεγχο ταυτότητας κωδικού πρόσβασης κατά τη σύνδεση σε βάσεις δεδομένων. Επικυρώστε τον κατακερματισμό του εισαγόμενου κωδικού πρόσβασης έναντι του κατακερματισμού του σωστού κωδικού πρόσβασης.

συμπέρασμα

Ελπίζω αυτό το σεμινάριο να σας βοήθησε να μάθετε για τη δημιουργία ασφαλών κατακερματισμών με την Python. Εδώ είναι τα βασικά συμπεράσματα:

  • Η ενότητα hashlib της Python παρέχει έτοιμες προς χρήση υλοποιήσεις αρκετών αλγορίθμων κατακερματισμού. Μπορείτε να λάβετε τη λίστα των αλγορίθμων που είναι εγγυημένοι στην πλατφόρμα σας χρησιμοποιώντας το hashlib.algorithms_guaranteed.
  • Για να δημιουργήσετε ένα αντικείμενο κατακερματισμού, μπορείτε να χρησιμοποιήσετε τον γενικό κατασκευαστή new() με τη σύνταξη: hashlib.new(“algo-name”). Εναλλακτικά, μπορείτε να χρησιμοποιήσετε τους κατασκευαστές που αντιστοιχούν στους συγκεκριμένους αλγόριθμους κατακερματισμού, όπως: hashlib.sha256() για τον κατακερματισμό SHA 256.
  • Αφού αρχικοποιήσετε τη συμβολοσειρά μηνύματος που πρόκειται να κατακερματιστεί και το αντικείμενο κατακερματισμού, μπορείτε να καλέσετε τη μέθοδο update() στο αντικείμενο κατακερματισμού, ακολουθούμενη από τη μέθοδο hexdigest() για να λάβετε τον κατακερματισμό.
  • Ο κατακερματισμός μπορεί να είναι χρήσιμος κατά τον έλεγχο της ακεραιότητας των τεχνουργημάτων και αρχείων λογισμικού, την αποθήκευση ευαίσθητων πληροφοριών σε βάσεις δεδομένων και πολλά άλλα.

Στη συνέχεια, μάθετε πώς να κωδικοποιείτε μια γεννήτρια τυχαίων κωδικών πρόσβασης στην Python.