Βαθμωτά και συμβολοσειρές

crypt#

Μονόδρομος κατακερματισμός τύπου passwd(5) μιας συμβολοσειράς απλού κειμένου με salt.

Η crypt είναι λεπτό περιτύλιγμα της συνάρτησης crypt(3) της C library του συστήματος. Μετατρέπει το PLAINTEXT και το SALT σε μια σύντομη συμβολοσειρά - μια σύνοψη - και την επιστρέφει. Τα ίδια PLAINTEXT και SALT παράγουν πάντα την ίδια σύνοψη· μικρές αλλαγές σε οποιοδήποτε από τα δύο παράγουν εντελώς διαφορετική σύνοψη. Δεν υπάρχει αντίστροφη συνάρτηση: δεν μπορείτε να ανακτήσετε το PLAINTEXT από μια σύνοψη.

Προειδοποίηση

Η crypt δεν είναι συνάρτηση κρυπτογράφησης γενικής χρήσης, παρά το όνομα. Δεν μπορεί να αναιρεθεί. Δεν είναι επίσης σύγχρονος κατακερματισμός κωδικών πρόσβασης στις περισσότερες παραδοσιακές διαμορφώσεις - το ιστορικό σχήμα Unix εξετάζει μόνο τα πρώτα οκτώ bytes του PLAINTEXT και παράγει σύνοψη 13 bytes πάνω σε salt 12 bits, που είναι ακατάλληλο για την προστασία κωδικών πρόσβασης από σύγχρονους επιτιθέμενους. Αυτό για το οποίο είναι κατάλληλη η crypt είναι η επαλήθευση μιας συμβολοσειράς που παρείχε ο χρήστης έναντι μιας ήδη αποθηκευμένης σύνοψης που έχει παραγάγει η crypt του ίδιου συστήματος. Για οτιδήποτε άλλο - κρυπτογράφηση, παραγωγή κλειδιών, ή κατακερματισμό μεγάλων δεδομένων - χρησιμοποιήστε μια αληθινή κρυπτογραφική βιβλιοθήκη. Δείτε Δείτε επίσης παρακάτω.

Σύνοψη#

crypt PLAINTEXT, SALT

Και τα δύο ορίσματα είναι συμβολοσειρές. Η τιμή επιστροφής είναι μια σύνοψη συμβολοσειράς.

Τι επιστρέφεται#

Μια συμβολοσειρά της οποίας η ακριβής μορφή εξαρτάται από την υλοποίηση της crypt(3) του υπολογιστή. Παραδοσιακά είναι 13 bytes: δύο bytes salt ακολουθούμενα από 11 bytes από το σύνολο [./0-9A-Za-z]. Οι σύγχρονες glibc, musl και BSD libcs δέχονται εκτεταμένα salts που επιλέγουν ισχυρότερα σχήματα (MD5, SHA-256, SHA-512, bcrypt, yescrypt) και επιστρέφουν μεγαλύτερες συνόψεις στη μορφή αρχείου passwd $id$salt$hash.

Αντιμετωπίστε τη σύνοψη ως αδιαφανή. Μην την αναλύετε, μην υποθέτετε μήκος, και μην υποθέτετε ποια bytes του SALT κατανάλωσε η υλοποίηση. Ο σωστός τρόπος για να επαληθεύσετε ένα απλό κείμενο έναντι μιας υπάρχουσας σύνοψης είναι να περάσετε την ίδια τη σύνοψη πίσω ως salt:

if (crypt($plain, $digest) eq $digest) { ... }

Το salt που χρησιμοποιήθηκε για τη δημιουργία της σύνοψης είναι ενσωματωμένο στη σύνοψη, οπότε αυτό επανατρέχει το ίδιο σχήμα με τις ίδιες παραμέτρους στο υποψήφιο απλό κείμενο. Κώδικας γραμμένος έτσι λειτουργεί με το κλασικό σχήμα DES και με κάθε σύγχρονη επέκταση που εκθέτει μια δοθείσα crypt(3), χωρίς να χρειάζεται να γνωρίζετε ποιο σχήμα παρήγαγε την αποθηκευμένη σύνοψη.

Καθολική κατάσταση που επηρεάζει#

Η crypt δεν διαβάζει ούτε γράφει καμία ειδική μεταβλητή της Perl. Σε είσοδο Unicode μπορεί να εκπέμψει μοιραίο σφάλμα Wide character in crypt (δείτε Οριακές περιπτώσεις).

Παραδείγματα#

Επαλήθευση κωδικού πρόσβασης έναντι αποθηκευμένης σύνοψης τύπου passwd:

my $stored = (getpwuid($<))[1];       # encrypted field from passwd

print "Password: ";
chomp(my $word = <STDIN>);

if (crypt($word, $stored) eq $stored) {
    print "ok\n";
} else {
    die "Sorry...\n";
}

Δημιουργία φρέσκιας σύνοψης για νέο κωδικό πρόσβασης χρησιμοποιώντας τυχαίο salt δύο χαρακτήρων από το κλασικό αλφάβητο. Το σύνολο είναι μόνο σύσταση· οι ακριβείς χαρακτήρες που γίνονται δεκτοί σε ένα salt είναι ό,τι επιτρέπει η crypt(3) του υπολογιστή, και η Perl δεν επιβάλλει δικό της περιορισμό:

my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
my $salt  = $chars[rand 64] . $chars[rand 64];
my $hash  = crypt($plaintext, $salt);

Αίτημα για συγκεκριμένο σύγχρονο σχήμα με χρήση εκτεταμένου salt (glibc και συμβατές libcs). Το πρόθεμα $id$ επιλέγει τον αλγόριθμο - το $1$ είναι MD5-crypt, το $5$ είναι SHA-256-crypt, το $6$ είναι SHA-512-crypt, το $2b$ είναι bcrypt όπου υποστηρίζεται:

my $hash = crypt($plaintext, '$6$rounds=100000$' . $random_salt);

Επαναεπαλήθευση με χρήση της αποθηκευμένης σύνοψης ως salt - ανεξάρτητη από το σχήμα:

my $candidate = crypt($plaintext, $stored_digest);
my $match     = $candidate eq $stored_digest;

Η σύγκριση σταθερού χρόνου των δύο συνόψεων εξακολουθεί να είναι ευθύνη του καλούντος· η απλή eq διαρρέει πληροφορία χρονισμού. Αν το μοντέλο απειλών το απαιτεί, συγκρίνετε bit-προς-bit με βρόχο που δεν βραχυκυκλώνει, ή χρησιμοποιήστε ρουτίνα σύγκρισης από κρυπτογραφικό άρθρωμα.

Οριακές περιπτώσεις#

  • Αποκοπή πρώτων-8-bytes στο κλασικό DES. Στην παραδοσιακή crypt(3) του Unix, μόνο τα πρώτα οκτώ bytes του PLAINTEXT επηρεάζουν τη σύνοψη: η crypt("password123", $s) και η crypt("password456", $s) συγκρούονται. Τα εκτεταμένα σχήματα ($1$, $5$, $6$, $2b$, …) δεν έχουν αυτό το όριο, αλλά το κλασικό σχήμα είναι αυτό που λαμβάνετε από salt δύο bytes χωρίς πρόθεμα.

  • Οι υποθέσεις για το μήκος του salt είναι λάθος. Μην υποθέτετε ότι η substr($digest,0,2) είναι το salt. Οι εκτεταμένες συνόψεις μεταφέρουν το salt σε διαφορετική θέση και με διαφορετικό μήκος. Επαναχρησιμοποιήστε την πλήρη σύνοψη ως όρισμα salt (crypt($plain, $digest)) και αφήστε την crypt(3) να την αναλύσει.

  • Είσοδος Unicode. Αν το PLAINTEXT ή το SALT περιέχει χαρακτήρες πάνω από το σημείο κώδικα 255, η Perl επιχειρεί να υποβαθμίσει ένα αντίγραφο της συμβολοσειράς σε bytes πριν καλέσει την crypt(3). Αν κάθε χαρακτήρας χωρά σε ένα byte, η υποβάθμιση πετυχαίνει σιωπηλά. Αν δεν χωρά κάποιος, η crypt πεθαίνει με Wide character in crypt. Κωδικοποιήστε ρητά (π.χ. Encode::encode_utf8) αν το απλό κείμενό σας μπορεί να περιέχει ευρείς χαρακτήρες.

  • Μη υποστηριζόμενο σχήμα επιστρέφει αποτυχία. Το πέρασμα ενός προθέματος $id$ που δεν κατανοεί η crypt(3) του υπολογιστή τυπικά επιστρέφει undef ή μια σύντομη συμβολοσειρά που ξεκινά με *0 ή *1. Πάντα ελέγχετε τη μορφή επιστροφής πριν τη χρησιμοποιήσετε.

  • Η crypt(3) μπορεί να απουσιάζει ή να είναι περιορισμένη. Σε μικρό αριθμό υπολογιστών η συνάρτηση της βιβλιοθήκης έχει αφαιρεθεί ή αντικατασταθεί με stub για λόγους ελέγχου εξαγωγών. Η crypt στην Perl είναι τόσο ικανή όσο η υποκείμενη κλήση libc· αν η κλήση libc είναι stub, τότε το ίδιο ισχύει και εδώ.

  • Ακατάλληλη για κατακερματισμό μεγάλων δεδομένων. Η crypt αγνοεί το μεγαλύτερο μέρος της εισόδου της στο κλασικό σχήμα και είναι αργή ανά κλήση στα τεντωμένα σχήματα. Είναι το λάθος εργαλείο για άθροισμα ελέγχου αρχείων ή για δόμηση αποθήκευσης διευθυνσιοδοτούμενης μέσω περιεχομένου.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42. Η pperl αποστέλλει στην crypt(3) του υπολογιστή με τον ίδιο τρόπο όπως η perl5, οπότε οι αποδεκτές μορφές salt και η ακριβής μορφή της σύνοψης ταιριάζουν με ό,τι παράγει η βιβλιοθήκη του συστήματος - συμπεριλαμβανομένης της διαθεσιμότητας των εκτεταμένων σχημάτων $1$/$5$/$6$/$2b$.

Δείτε επίσης#

  • Digest::MD5 - MD5-128 πάνω από αυθαίρετες συμβολοσειρές bytes· χρησιμοποιήστε για αποτύπωση δεδομένων, όχι για αποθήκευση κωδικών πρόσβασης

  • Digest::SHA - συνόψεις οικογένειας SHA-1/2· χρησιμοποιήστε για ελέγχους ακεραιότητας και ως δομικό στοιχείο για HMAC και παραγωγή κλειδιών

  • Crypt::Bcrypt, Crypt::Argon2, Crypt::Passphrase - αρθρώματα CPAN για σύγχρονο κατακερματισμό κωδικών πρόσβασης· προτιμήστε αυτά αντί της crypt για κάθε νέο κώδικα επαλήθευσης κωδικών

  • Crypt::Eksblowfish, Crypt::ScryptKDF - αρθρώματα CPAN για παραγωγή κλειδιών βάσει bcrypt και scrypt

  • getpwuid - ανακτά το πεδίο κρυπτογραφημένου κωδικού από την τοπική βάση δεδομένων passwd· το έβδομο πεδίο της είναι η σύνοψη που περνάτε ως SALT κατά την επαλήθευση

  • chomp - αφαιρεί τον τελικό newline από έναν κωδικό πρόσβασης που διαβάστηκε με <STDIN> πριν τον περάσετε στην crypt