Προγραμματισμός

Κατασκευάστε ασφαλείς δικτυωμένες εφαρμογές με πιστοποιητικά, Μέρος 2

Για να δημιουργήσετε ασφαλείς εφαρμογές, πρέπει να μάθετε τα εργαλεία του εμπορίου. Για να σας βοηθήσω να εξοικειωθείτε με αυτές τις έννοιες, σας παρουσίασα στην κρυπτογράφηση δημόσιου κλειδιού στο Μέρος 1 και εξήγησα πώς αποφεύγει τα προβλήματα ανταλλαγής κλειδιών που συνοδεύουν την κρυπτογράφηση μυστικού κλειδιού. Ερεύνησα επίσης τη σχέση μεταξύ εμπιστοσύνης και κλιμάκωσης της κρυπτογράφησης δημόσιου κλειδιού και εξήγησα πώς τα πιστοποιητικά και η υποδομή δημόσιου κλειδιού (PKI) επιτρέπουν την εμπιστοσύνη σε ευρύτερη κλίμακα από την κρυπτογραφία δημόσιου κλειδιού από μόνη της. Τέλος, περιέγραψα τα πιστοποιητικά και τις αλυσίδες πιστοποιητικών και εξήγησα πώς σχετίζονται με τις ΑΠ (αρχές έκδοσης πιστοποιητικών).

Διατίθενται πολλές διαφορετικές εκδόσεις πιστοποιητικών, όπως το SDSI (απλή κατανεμημένη υποδομή ασφαλείας), το PGP (αρκετά καλό απόρρητο) και το X.509. Αυτό το μήνα, για να επεκτείνω περαιτέρω το λεξιλόγιο ασφαλείας σας, θα περιγράψω τη μορφή πιστοποιητικού που οδηγεί στο πακέτο και αποτελεί βασικό στοιχείο των αναδυόμενων προτύπων PKI: το πιστοποιητικό X.509.

Μπορείτε να διαβάσετε ολόκληρη τη σειρά στα πιστοποιητικά:

  • Μέρος 1: Τα πιστοποιητικά προσθέτουν αξία στην κρυπτογράφηση δημόσιου κλειδιού
  • Μέρος 2: Μάθετε να χρησιμοποιείτε τα πιστοποιητικά X.509
  • Μέρος 3: Χρησιμοποιήστε τις κλάσεις Java CRL και X509CRL
  • Μέρος 4: Έλεγχος ταυτότητας πελατών και διακομιστών και επαλήθευση αλυσίδων πιστοποιητικών

Η μορφή X.509 λεπτομερώς

Η Διεθνής Ένωση Τηλεπικοινωνιών (ITU) ανέπτυξε και δημοσίευσε τη μορφή πιστοποιητικού X.509, η οποία επιλέχθηκε από την ομάδα εργασίας του Δημόσιου Κλειδιού Υποδομής X.509 (PKIX) της Ομάδας Εργασίας Μηχανικής Διαδικτύου (IETF). Εάν τα ακρωνύμια δείχνουν δύναμη, το X.509 έχει σαφώς ισχυρούς συμμάχους.

Χρησιμοποιώντας μια σημείωση που ονομάζεται ASN.1 (Abstract Syntax Notation One), το πρότυπο X.509 καθορίζει τη μορφή ενός πιστοποιητικού. Το ASN.1 είναι μια τυποποιημένη γλώσσα που περιγράφει αφηρημένους τύπους δεδομένων με τρόπο ανεξάρτητο από την πλατφόρμα.

Το έγγραφο "Υποδομή δημόσιου κλειδιού Διαδικτύου X.509 - Πιστοποιητικό και προφίλ CRL" (ανατρέξτε στην ενότητα Πόροι για έναν σύνδεσμο) που δημοσιεύτηκε από την ομάδα εργασίας PKIX περιγράφει μια μορφή πιστοποιητικού X.509 σε όρους σημείωσης ASN.1. Είναι μια συναρπαστική ανάγνωση αν σας ενδιαφέρει κάτι τέτοιο.

Ένας τύπος δεδομένων - όπως ένα πιστοποιητικό - ορίζεται στο ASN.1 δεν είναι χρήσιμος έως ότου μπορεί να ορίσει σαφώς τον τρόπο αναπαραγωγής μιας παρουσίας ενός τύπου δεδομένων ως μια σειρά bits. Για να δώσει στον τύπο δεδομένων αυτήν τη λειτουργικότητα, το ASN.1 χρησιμοποιεί τους Διακεκριμένους Κανόνες Κωδικοποίησης (DER), οι οποίοι καθορίζουν τον τρόπο κωδικοποίησης μοναδικού αντικειμένου ASN.1.

Με ένα αντίγραφο του ορισμού ASN.1 ενός πιστοποιητικού X.509 και μια γνώση του DER, μπορείτε να γράψετε μια εφαρμογή Java που θα διαβάσει και θα γράψει πιστοποιητικά X.509 και θα λειτουργήσει με παρόμοιες εφαρμογές γραμμένες σε άλλες γλώσσες προγραμματισμού. Ευτυχώς, πιθανότατα δεν θα χρειαστεί ποτέ να αντιμετωπίσετε τόσο μεγάλο πρόβλημα, επειδή η πλατφόρμα Java 2, Standard Edition (J2SE) διαθέτει ενσωματωμένη υποστήριξη για πιστοποιητικά X.509.

X.509 για (σχεδόν) τίποτα

Όλες οι κλάσεις και οι διεπαφές που σχετίζονται με το πιστοποιητικό βρίσκονται στο πακέτο java.security.cert. Όπως και τα άλλα μέλη της οικογένειας API ασφαλείας της Sun, το πακέτο πιστοποιητικών σχεδιάστηκε γύρω από το πρότυπο του εργοστασίου, στο οποίο μία ή περισσότερες κλάσεις Java ορίζουν μια γενική διεπαφή για την προβλεπόμενη λειτουργικότητα ενός πακέτου. Τα μαθήματα είναι αφηρημένα, επομένως οι εφαρμογές δεν μπορούν να τα τοποθετήσουν άμεσα. Αντίθετα, η παρουσία μιας εργοστασιακής κλάσης δημιουργεί και επιστρέφει παρουσίες των συγκεκριμένων υποτύπων των αφηρημένων τάξεων. Το εργοστασιακό παράδειγμα παρακάμπτει την ισχυρή πληκτρολόγηση της Java, αλλά σε αντάλλαγμα, επιτρέπει στον κώδικα να εκτελείται χωρίς μεταγλώττιση σε ένα ευρύτερο φάσμα περιβάλλοντος.

ο java.security.cert.Certificate και java.security.cert.CRL οι αφηρημένες τάξεις καθορίζουν τη διεπαφή. Αντιπροσωπεύουν πιστοποιητικά και λίστες ανάκλησης πιστοποιητικών (CRL), αντίστοιχα. ο Πιστοποιητικό εργοστάσιο τάξη είναι το εργοστάσιό τους.

ο java.security.cert Το πακέτο περιέχει συγκεκριμένες υλοποιήσεις του Πιστοποιητικό και CRL αφηρημένες τάξεις: το X509 Πιστοποιητικό και X509CRL τάξεις. Αυτές οι δύο κατηγορίες εφαρμόζουν βασικές λειτουργίες πιστοποιητικών και CRL και, στη συνέχεια, την επεκτείνουν με λειτουργικότητα X.509. Όταν ένα Πιστοποιητικό εργοστάσιο Το instance επιστρέφει μια παρουσία οποιασδήποτε κλάσης, ένα πρόγραμμα μπορεί είτε να το χρησιμοποιήσει ως έχει είτε να το μεταφέρει ρητά στη φόρμα X.509.

Στο java.security.cert πακέτο, διεπαφή X509Επέκταση ορίζει μια διεπαφή για τις επεκτάσεις ενός πιστοποιητικού X.509. Οι επεκτάσεις είναι προαιρετικά στοιχεία που παρέχουν έναν μηχανισμό για τους δημιουργούς πιστοποιητικών να συσχετίζουν πρόσθετες πληροφορίες με ένα πιστοποιητικό. Για παράδειγμα, ένα πιστοποιητικό μπορεί να χρησιμοποιεί το KeyUsage επέκταση για να υποδείξει ότι μπορεί να χρησιμοποιηθεί για υπογραφή κώδικα.

ο java.security.cert Το πακέτο περιλαμβάνει επίσης μια κλάση διεπαφής παρόχου υπηρεσιών (SPI). ΕΝΑ πάροχος κρυπτογραφικών υπηρεσιών που επιθυμεί να υποστηρίξει έναν τύπο πιστοποιητικού επεκτείνει το SPI. Το Java 2 συνοδεύεται από πιστοποιητικό SPI για X.509.

Ας ρίξουμε μια πιο λεπτομερή ματιά στις τάξεις και τις διεπαφές στο java.security.cert πακέτο. Για λόγους συντομίας, θα συζητήσω μόνο τις πιο χρήσιμες μεθόδους. Για πιο ολοκληρωμένη κάλυψη, σας ενθαρρύνω να διαβάσετε την τεκμηρίωση της Sun. (Δείτε πόρους.)

java.security.cert.CertificateFactory

Η ιστορία ξεκινά με java.security.cert.CertificateFactory. ο Πιστοποιητικό εργοστάσιο τάξη έχει στατικές μεθόδους που δημιουργούν ένα Πιστοποιητικό εργοστάσιο παράδειγμα για έναν συγκεκριμένο τύπο πιστοποιητικού και μεθόδους που δημιουργούν τόσο πιστοποιητικά όσο και CRL από δεδομένα που παρέχονται σε μια ροή εισόδου. Θα περιγράψω εν συντομία τις πιο σημαντικές μεθόδους και μετά θα εξηγήσω πώς να χρησιμοποιώ αυτές τις μεθόδους κατά τη δημιουργία πιστοποιητικών X.509 και CRL. Αργότερα στο άρθρο, θα παρουσιάσω κώδικα που δείχνει τις μεθόδους σε δράση.

  • δημόσιο στατικό πιστοποιητικόFactory getInstance (String stringType) και δημόσιο στατικό πιστοποιητικόFactory getInstance (String stringType, String stringProvider) να δημιουργήσετε και να επιστρέψετε μια παρουσία εργοστασίου πιστοποιητικών για τον τύπο πιστοποιητικού που καθορίζεται από το τύπος συμβολοσειράς παράμετρος. Για παράδειγμα, εάν η τιμή του τύπος συμβολοσειράς είναι η συμβολοσειρά "X.509", και οι δύο μέθοδοι θα επιστρέψουν μια παρουσία του Πιστοποιητικό εργοστάσιο τάξη κατάλληλη για τη δημιουργία παρουσιών των τάξεων X509 Πιστοποιητικό και X509CRL. Η δεύτερη μέθοδος δέχεται το όνομα ενός συγκεκριμένου παρόχου κρυπτογραφικών υπηρεσιών ως όρισμα και χρησιμοποιεί αυτόν τον πάροχο αντί για την προεπιλογή.
  • δημόσιο τελικό Certificate createCertificate (InputStream inputstream) δημιουργεί και επιστρέφει ένα πιστοποιητικό χρησιμοποιώντας δεδομένα που διαβάζονται από τα παρεχόμενα InputStream παράδειγμα. Εάν η ροή περιέχει περισσότερα από ένα πιστοποιητικά και η ροή υποστηρίζει το σημάδι() και επαναφορά() λειτουργίες, η μέθοδος θα διαβάσει ένα πιστοποιητικό και θα αφήσει τη ροή τοποθετημένη πριν από το επόμενο.
  • δημόσιο τελικό Συλλογή δημιουργήστε πιστοποιητικά (InputStream inputstream) δημιουργεί και επιστρέφει μια συλλογή πιστοποιητικών χρησιμοποιώντας δεδομένα που διαβάζονται από τα παρεχόμενα InputStream παράδειγμα. Εάν η δεδομένη ροή δεν υποστηρίζει σημάδι() και επαναφορά(), η μέθοδος θα καταναλώσει ολόκληρη τη ροή.
  • δημόσιο τελικό CRL createCRL (InputStream inputstream) δημιουργεί και επιστρέφει ένα CRL χρησιμοποιώντας δεδομένα που διαβάζονται από τα παρεχόμενα InputStream παράδειγμα. Εάν η ροή περιέχει περισσότερα από ένα CRL και υποστηρίζει το σημάδι() και επαναφορά() λειτουργίες, η μέθοδος θα διαβάσει ένα CRL και θα αφήσει τη ροή τοποθετημένη πριν από την επόμενη.
  • δημόσιο τελικό Συλλογή createCRLs (InputStream inputstream) δημιουργεί και επιστρέφει μια συλλογή CRL χρησιμοποιώντας δεδομένα που διαβάζονται από τα παρεχόμενα InputStream παράδειγμα. Εάν η δεδομένη ροή δεν υποστηρίζει σημάδι() και επαναφορά(), δημόσιο τελικό Collection createCRLs (InputStream inputstream) θα καταναλώσει ολόκληρη τη ροή.

Είναι σημαντικό να κατανοήσουμε πώς συμπεριφέρονται αυτές οι τέσσερις μέθοδοι κατά τη δημιουργία εμφανίσεων X.509 από μια ροή δεδομένων. Ας ΡΙΞΟΥΜΕ μια ΜΑΤΙΑ.

ο δημιουργία πιστοποιητικού () και δημιουργίαCRL () Οι μέθοδοι αναμένουν ότι τα περιεχόμενα της ροής εισόδου περιέχουν κωδικοποιήσεις DER ενός πιστοποιητικού ή ενός CRL, αντίστοιχα.

Και τα δύο δημιουργία πιστοποιητικών () και δημιουργίαCRL () Οι μέθοδοι αναμένουν ότι τα περιεχόμενα της ροής εισόδου θα περιέχουν είτε μια ακολουθία αναπαραστάσεων με κωδικοποίηση DER είτε ένα πιστοποιητικό συμμόρφωσης PKCS # 7 (Public-Key Cryptography Standard # 7) ή CRL set. (Δείτε πόρους για συνδέσμους.)

java.security.cert.Certificate

java.security.cert.Certificate ορίζει τη διεπαφή κοινή για όλους τους τύπους πιστοποιητικών: X.509, PGP και μια μικρή χούφτα άλλων. Οι πιο σημαντικές μέθοδοι αυτής της τάξης είναι:

  • δημόσια περίληψη PublicKey getPublicKey () επιστρέφει το δημόσιο κλειδί που σχετίζεται με την παρουσία πιστοποιητικού στην οποία καλείται αυτή η μέθοδος.
  • δημόσιο αφηρημένο byte [] getEncoded () επιστρέφει την κωδικοποιημένη φόρμα του πιστοποιητικού.
  • δημόσια περίληψη κενού επαλήθευση (PublicKey publickey) και δημόσια περίληψη κενού επαλήθευση (PublicKey publickey, String stringProvider) επαληθεύστε ότι το ιδιωτικό κλειδί που αντιστοιχεί στο παρεχόμενο δημόσιο κλειδί υπέγραψε το εν λόγω πιστοποιητικό. Εάν τα κλειδιά δεν ταιριάζουν, και οι δύο μέθοδοι ρίχνουν ένα Υπογραφή Εξαίρεση.

java.security.cert.X509 Πιστοποιητικό

Η τάξη java.security.cert.X509 Πιστοποιητικό επεκτείνει το Πιστοποιητικό κλάση που περιγράφεται παραπάνω και προσθέτει λειτουργικότητα ειδικά για το X.509. Αυτή η τάξη είναι σημαντική επειδή συνήθως αλληλεπιδράτε με πιστοποιητικά σε αυτό το επίπεδο και όχι ως βασική τάξη.

  • δημόσιο αφηρημένο byte [] getEncoded () επιστρέφει την κωδικοποιημένη μορφή αυτού του πιστοποιητικού, όπως παραπάνω. Η μέθοδος χρησιμοποιεί την κωδικοποίηση DER για το πιστοποιητικό.

Τα περισσότερα java.security.cert.X509 ΠιστοποιητικόΗ πρόσθετη λειτουργικότητα αποτελείται από μεθόδους ερωτήματος που επιστρέφουν πληροφορίες σχετικά με το πιστοποιητικό. Παρουσίασα τις περισσότερες από αυτές τις πληροφορίες στο Μέρος 1. Ακολουθούν οι μέθοδοι:

  • δημόσια περίληψη int getVersion () επιστρέφει την έκδοση του πιστοποιητικού.
  • δημόσια περίληψη Principal getSubjectDN () επιστρέφει πληροφορίες που προσδιορίζουν το θέμα του πιστοποιητικού.
  • δημόσια περίληψη Principal getIssuerDN () επιστρέφει πληροφορίες που προσδιορίζουν τον εκδότη του πιστοποιητικού, η οποία είναι συνήθως η ΑΠ, αλλά μπορεί να είναι το θέμα εάν το πιστοποιητικό είναι αυτο-υπογεγραμμένο.
  • δημόσια περίληψη Ημερομηνία getNotBefore () και δημόσια περίληψη Ημερομηνία getNotAfter () επιστρέφουν τιμές που περιορίζουν τη χρονική περίοδο κατά την οποία ο εκδότης είναι διατεθειμένος να εγγυηθεί το δημόσιο κλειδί του θέματος.
  • δημόσια περίληψη BigInteger getSerialNumber () επιστρέφει τον σειριακό αριθμό του πιστοποιητικού. Ο συνδυασμός του ονόματος εκδότη πιστοποιητικού και του σειριακού αριθμού είναι η μοναδική του ταυτότητα. Αυτό το γεγονός είναι ζωτικής σημασίας για την ανάκληση πιστοποιητικών, το οποίο θα συζητήσω λεπτομερέστερα τον επόμενο μήνα.
  • δημόσια περίληψη String getSigAlgName () και δημόσια περίληψη String getSigAlgOID () επιστρέψτε πληροφορίες σχετικά με τον αλγόριθμο που χρησιμοποιείται για την υπογραφή του πιστοποιητικού.

Οι ακόλουθες μέθοδοι επιστρέφουν πληροφορίες σχετικά με τις επεκτάσεις που ορίζονται για το πιστοποιητικό. Θυμηθείτε, οι επεκτάσεις είναι μηχανισμοί για τη σύνδεση πληροφοριών με ένα πιστοποιητικό. εμφανίζονται μόνο σε πιστοποιητικά έκδοσης 3.

  • δημόσια περίληψη int getBasicConstraints () επιστρέφει το μήκος της διαδρομής περιορισμών ενός πιστοποιητικού από το Βασικές περιορισμοί επέκταση, εάν ορίζεται. Η διαδρομή περιορισμών καθορίζει τον μέγιστο αριθμό πιστοποιητικών CA που ενδέχεται να ακολουθούν αυτό το πιστοποιητικό σε μια διαδρομή πιστοποίησης.
  • δημόσια αφηρημένη boolean [] getKeyUsage () επιστρέφει τον σκοπό του πιστοποιητικού όπως κωδικοποιείται στο KeyUsage επέκταση.
  • δημόσιο σύνολο getCriticalExtensionOIDs () και δημόσιο σύνολο getNonCriticalExtensionOID () επιστρέψτε μια συλλογή αναγνωριστικών αντικειμένων (OID) για τις επεκτάσεις που χαρακτηρίζονται κρίσιμες και μη κρίσιμες, αντίστοιχα. Το OID είναι μια ακολουθία ακεραίων που αναγνωρίζει καθολικά έναν πόρο.

Δεν θέλω να σας αφήσω χωρίς κωδικό για να παίξετε, οπότε αντί να μελετήσετε CRL, το οποίο είναι από μόνο του ένα πλήρες θέμα, θα παρουσιάσω τον κώδικα και θα αφήσω CRL για το Μέρος 3.

Ο κώδικας

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