Η πρώτη γραμμή καταγράφει τις ακριβείς παραμέτρους που χρησιμοποιήθηκαν (αλγόριθμος, ανάγνωση, μεγέθη εισόδου), ώστε ένα αποτέλεσμα που αντιγράφηκε να είναι πάντα αναπαράξιμο.
HMAC, PBKDF2 και HKDF — κατακερματισμός με κλειδί εξηγημένος από το μηδέν
Σε μία πρόταση: ένας απλός κατακερματισμός όπως το SHA-256 μπορεί να υπολογιστεί από οποιονδήποτε, οπότε δεν αποδεικνύει τίποτα για το ποιος έστειλε ένα μήνυμα· το HMAC αναμιγνύει ένα μυστικό κλειδί, ώστε μόνο όσοι κατέχουν το κλειδί να μπορούν να παράγουν (ή να επαληθεύσουν) το digest· το PBKDF2 και το HKDF επαναχρησιμοποιούν την ίδια μηχανή HMAC για να μετατρέπουν μυστικά σε κλειδιά, αργά για κωδικούς και γρήγορα για υλικό που είναι ήδη τυχαίο.
Τι είναι το HMAC (RFC 2104)
Η κατασκευή. Το HMAC είναι δύο εκτελέσεις κατακερματισμού, όχι μία. Το κλειδί συμπληρώνεται στο μέγεθος μπλοκ του κατακερματισμού (64 byte για MD5/SHA-1/SHA-256, 128 για SHA-384/512)· το μήνυμα κατακερματίζεται μία φορά με το κλειδί XOR ένα σταθερό εσωτερικό pad, και το digest αυτό κατακερματίζεται ξανά με το κλειδί XOR ένα σταθερό εξωτερικό pad. Αυτό το διπλό σάντουιτς είναι αποδεδειγμένα ασφαλές, εφόσον ο υποκείμενος κατακερματισμός είναι αξιοπρεπής ψευδοτυχαία συνάρτηση — γι' αυτό το HMAC-MD5 αντέχει ακόμη στις πρακτικές επιθέσεις σύγκρουσης που έσπασαν το απλό MD5 (αν και αποσύρθηκε ούτως ή άλλως, βλ. παρακάτω).
Κλειδιά. Οποιοδήποτε μήκος κλειδιού λειτουργεί: μικρότερο από το μέγεθος μπλοκ χρησιμοποιείται όπως είναι (αλλά κάτω από 32 byte αποδοκιμάζεται), μεγαλύτερο κατακερματίζεται πρώτα. Η ίδια σελίδα επιτρέπει να πληκτρολογηθεί το κλειδί ως κείμενο, hex ή Base64, ώστε ένα κλειδί παραγωγής 64 δεκαεξαδικών χαρακτήρων να μπορεί να επικολληθεί χωρίς να εκληφθεί ως κείμενο 64 χαρακτήρων· η ανάγνωση καταγράφεται στη γραμμή εξόδου ακριβώς γι' αυτόν τον λόγο.
Πού συναντάται. Το πεδίο HS256 της κεφαλίδας JWT είναι κυριολεκτικά HMAC-SHA-256 πάνω στα μέρη του διακριτικού κωδικοποιημένα σε base64url (ο Αποκωδικοποιητής JWT σε αυτόν τον ιστότοπο υπολογίζει ακριβώς αυτό όταν επικολληθεί ένα μυστικό HS256). Οι υπογραφές webhook (Stripe, GitHub), το AWS SigV4, η προστασία εγγραφών TLS (παλαιότερες εκδόσεις) και ο συγγενής του OpenSSH umac-64@openssh.com ανήκουν όλα στην ίδια οικογένεια.
Γιατί όχι απλώς hash(message || key); Επέκταση μήκους: κάθε κατακερματισμός της οικογένειας MD5/SHA-1/SHA-2 επιτρέπει σε όποιον γνωρίζει το H(secret || msg) να υπολογίσει το H(secret || msg || padding || anything) χωρίς το μυστικό. Ο διαχωρισμός εσωτερικού/εξωτερικού του HMAC καταργεί αυτή την κατηγορία επίθεσης. Είναι το πιο συνηθισμένο λάθος DIY στον κώδικα υπογραφής API — και ο λόγος ύπαρξης του HMAC.
Τι είναι το PBKDF2 (RFC 8018)
Αργό εκ σχεδιασμού. Ένας κωδικός έχει ίσως 40 bit πραγματικής εντροπίας· η GPU ενός επιτιθέμενου δοκιμάζει δισεκατομμύρια SHA-256 ανά δευτερόλεπτο. Το PBKDF2 εκτελεί το HMAC(password, salt) ξανά και ξανά — iter φορές — ώστε κάθε εικασία να κοστίζει τα ίδια iter HMAC για τον χρήστη και για τον επιτιθέμενο. Η προεπιλογή εδώ είναι 600 000 επαναλήψεις με HMAC-SHA-256, η βάση αναφοράς του OWASP Password Storage Cheat Sheet· ο ρυθμιστής φτάνει τα δέκα εκατομμύρια, επειδή οι οδηγίες ασφαλείας ανεβαίνουν καθώς επιταχύνεται το υλικό.
Salt. Ένα τυχαίο salt ανά κωδικό σημαίνει ότι οι πανομοιότυποι χρήστες δεν κατακερματίζονται πια πανομοιότυπα, και οι προυπολογισμένοι πίνακες (rainbow tables) γίνονται άχρηστοι. Δεν είναι μυστικό — αποθηκεύεται δίπλα στο hash — αρκεί να είναι μοναδικό. Τα 16 τυχαία byte είναι το συνηθισμένο μέτρο.
Γνωστή αδυναμία. Το PBKDF2 είναι δύσκολο για τον επεξεργαστή, αλλά όχι δύσκολο για τη μνήμη: οι GPU και τα ASIC το παραλληλίζουν εξαιρετικά. Γι' αυτό η σύγχρονη οδηγία είναι το scrypt ή το Argon2id όπου σχεδιάζεται αποθήκευση κατακερματισμού κωδικών (η Γεννήτρια hash κωδικών αυτής της οικογένειας τα καλύπτει), ενώ το PBKDF2 παραμένει η σωστή επιλογή για συμβατότητα και ρυθμίσεις FIPS-140.
Τι είναι το HKDF (RFC 5869)
Εξαγωγή, και έπειτα επέκταση. Το HKDF κάνει δύο δουλειές. Εξαγωγή: συμπιέζει το, ενδεχομένως άνισο, υλικό κλειδιού εισόδου (για παράδειγμα ένα κοινό μυστικό Diffie–Hellman) μαζί με ένα salt σε ένα σύντομο ψευδοτυχαίο κλειδί PRK = HMAC(salt, IKM). Επέκταση: επεκτείνει το PRK σε οποιοδήποτε μήκος έως 255 μπλοκ κατακερματισμού, με κάθε μπλοκ εξόδου αλυσιδωτό με το προηγούμενο και σημασμένο από το πεδίο info. Το αποτέλεσμα είναι ότι ένα μυστικό μπορεί με ασφάλεια να δώσει ένα κλειδί κρυπτογράφησης, ένα κλειδί MAC και ένα IV, όλα διαχωρισμένα.
Όχι για κωδικούς πρόσβασης. Το HKDF υποθέτει ότι η είσοδός του έχει ήδη πλήρη εντροπία — κάνει ένα HMAC ανά 32 byte εξόδου, οπότε ένας ανθρώπινος κωδικός το περνά σχεδόν ακαριαία, ακριβώς ό,τι θέλει ο επιτιθέμενος. Η τροφοδοσία κωδικών στο HKDF αντί για το PBKDF2 είναι κλασικό σφάλμα σχεδιασμού· το πεδίο info προορίζεται για ετικέτες σκοπού ("client traffic key", "server iv"), όχι για επιπλέον εντροπία.
Πού συναντάται. Το TLS 1.3 παράγει κάθε κλειδί που χρησιμοποιεί από το μυστικό χειραψίας μέσω HKDF· το WireGuard, το Signal, το EAP-TLS 1.3 και το JSON Web Encryption (ως άμεσο KDF συμφωνίας κλειδιού) εμφανίζονται όλα στο ίδιο γενεαλογικό δέντρο.
Τιμές αναφοράς — αναπαραγωγή στη σελίδα
Οι δύο πρώτοι πίνακες είναι τα διανύσματα δοκιμής στα οποία βασίζονται το κουμπί Δείγμα και ο αυτοέλεγχος αυτής της σελίδας (κλειδί "key", μήνυμα “The quick brown fox jumps over the lazy dog”· και στη συνέχεια η περίπτωση τύπου RFC με κλειδί 16 byte 0x0b και μήνυμα “Hi There”). Όλα παράχθηκαν από ανεξάρτητη εγγενή υλοποίηση και επαληθεύτηκαν ξανά σε αυτή τη σελίδα.
HMAC του “fox”, κλειδί = key | Digest (hex) |
| HMAC-MD5 | 80070713463e7749b90c2dc24911e275 |
| HMAC-SHA-1 | de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 |
| HMAC-SHA-256 | f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8 |
| HMAC-SHA-384 | d7f4727e2c0b39ae0f1e40cc96f60242d5b7801841cea6fc592c5d3e1ae50700582a96cf35e1e554995fe4e03381c237 |
| HMAC-SHA-512 | b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a |
| Σημεία αναφοράς KDF | Παράμετροι | Έξοδος (hex, πρώτα byte) |
| PBKDF2-HMAC-SHA-1 | password / salt, c=4096, 32 byte | 4b007901b765489abead49d926f721d065a429c12e463f6c4cd79401085b03db |
| PBKDF2-HMAC-SHA-256 | password / salt, c=4096, 32 byte | c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a |
| HKDF-SHA-256 (RFC 5869 A.1) | IKM=0x0b×22, salt=00..0c, info=f0..f9, L=42 | 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865 |
| HKDF-SHA-256 (RFC 5869 A.2) | IKM=00..4f, salt=60..af, info=b0..ff, L=82 | b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c… |
| HKDF-SHA-256 (RFC 5869 A.3) | IKM=0x0b×22, κενό salt και info, L=42 | 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8 |
Συνηθισμένα λάθη
- Σύγχυση του HMAC με κρυπτογράφηση. Το HMAC αποδεικνύει ακεραιότητα και προέλευση (δεδομένου ενός κοινού μυστικού)· δεν κρύβει τίποτα. Όποιος δεν έχει το κλειδί εξακολουθεί να βλέπει ολόκληρο το μήνυμα.
- Σύγχυση του HMAC με ψηφιακή υπογραφή. Οι ψηφιακές υπογραφές βασίζονται σε δημόσιο κλειδί: ένας υπογράφει, όλοι επαληθεύουν. Το HMAC είναι συμμετρικό: κάθε επαληθευτής θα μπορούσε επίσης να πλαστογραφήσει. Για μη αποκήρυξη χρειάζονται RSA/ECDSA (βλ. το εργαλείο RSA αυτής της οικογένειας μόλις δημοσιευτεί), όχι HMAC.
- Ασυμφωνίες ανάγνωσης κλειδιού. Μια συμβολοσειρά 64 δεκαεξαδικών χαρακτήρων που επικολλάται στο πεδίο κλειδιού κειμένου γίνεται 64 byte, όχι 32 — και το HMAC αλλάζει εντελώς. Αυτή η σελίδα εκτυπώνει την ανάγνωση στη γραμμή εξόδου· όταν δύο εργαλεία διαφωνούν, αυτό είναι το πρώτο που πρέπει να συγκριθεί.
- Χαμηλές επαναλήψεις του PBKDF2. Οι 1 000 επαναλήψεις ήταν λογικές το 2000· σήμερα τις καταναλώνουν οι συστοιχίες GPU. Αν ένα σύστημα εξακολουθεί να αποθηκεύει κατακερματισμούς με 1 000 επαναλήψεις, να προγραμματιστεί μετανάστευση με επανακατακερματισμό κατά τη σύνδεση.
- HKDF σε κωδικό πρόσβασης. Ένα HMAC ανά μπλοκ εξόδου σημαίνει ότι ο κωδικός περνά ακαριαία — χρησιμοποιείται το PBKDF2 (ή Argon2id) για κωδικούς και το HKDF για μυστικά υψηλής εντροπίας.
- Επαναχρησιμοποίηση ενός παραγόμενου κλειδιού για όλα. Η διόρθωση είναι δωρεάν: παράγονται ξεχωριστά κλειδιά με διαφορετικές ετικέτες
info. Δύο κλειδιά από ένα IKM με διαφορετικές ετικέτες είναι ανεξάρτητα εκ σχεδιασμού.
Συχνές ερωτήσεις
Είναι σπασμένο το HMAC-MD5; Ως συνάρτηση κατακερματισμού ανθεκτική σε συγκρούσεις το MD5 έχει πεθάνει, αλλά η ασφάλεια του HMAC-MD5 εξαρτάται από το MD5 ως ψευδοτυχαία συνάρτηση, και δεν είναι γνωστή πρακτική διάσπαση. Παρ' όλα αυτά αποσύρθηκε — δεν υπάρχει λόγος να επιλεγεί έναντι του HMAC-SHA-256 εκτός από συμβατότητα με παλαιό πρωτόκολλο.
Πόσο μακρύ πρέπει να είναι το κλειδί HMAC; Τουλάχιστον όσο το μέγεθος εξόδου του κατακερματισμού (32 byte για SHA-256) και δημιουργημένο από CSPRNG. Επιτρέπεται κλειδί μικρότερο από το digest, αλλά κάθε bit κάτω από αυτό μειώνει άμεσα την ασφάλεια.
Το PBKDF2 με περισσότερες επαναλήψεις γίνεται “πιο ασφαλές” επ' αόριστον; Αυξάνει το κόστος του επιτιθέμενου γραμμικά, αλλά και το κόστος σύνδεσης γραμμικά. Το ζητούμενο είναι η επιλογή του μεγαλύτερου πλήθους που οι χρήστες αντέχουν — αυτό ακριβώς βαθμονομούν οι αριθμοί του OWASP.
Γιατί το HKDF περιορίζεται σε 255 × μέγεθος hash; Ο βρόχος επέκτασης είναι T(i) = HMAC(PRK, T(i-1) || info || i) με μετρητή ενός byte i — το 255 είναι η μεγαλύτερη τιμή του μετρητή, ένα αυστηρό δομικό όριο του RFC 5869, και όχι επιλογή πολιτικής.
Ποια είναι η διαφορά μεταξύ του PBKDF2 αυτής της σελίδας και της Γεννήτριας hash κωδικών; Ο ίδιος αλγόριθμος, διαφορετική δουλειά. Αυτή η σελίδα παράγει ακατέργαστα byte κλειδιού για χρήση αλλού· η σελίδα των κατακερματισμών κωδικών παράγει συμβολοσειρές αποθηκευμένων διαπιστευτηρίων (με ενσωματωμένο salt και παραμέτρους) και επαληθεύει υποψήφιες τιμές έναντι αυτών.